1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

large filesystem update. Filesysytem is now fully functional, everything should work.

- completely replaced CLodHandler, removed bitmaph and spriteh
- replaced CLodStream in favour of CCompressedStream (2 new files)
- renamed CResourceLoaderFactory and ResourceIndetifier to shorter names
NOTES:
- campaign loading is currently broken. Will fix.
- I am going to remove several unused files in several days (e.g. LodHandler)
This commit is contained in:
Ivan Savenko 2012-08-01 12:02:54 +00:00
parent 17a513c01b
commit b3c17d2788
55 changed files with 1319 additions and 767 deletions

View File

@ -1,6 +1,7 @@
#include "StdInc.h"
#include "CCreatureAnimation.h"
#include "../../lib/Filesystem/CResourceLoader.h"
#include "../../lib/CLodHandler.h"
#include "../../lib/VCMI_Lib.h"
#include "../../lib/vcmi_endian.h"
@ -42,7 +43,9 @@ void CCreatureAnimation::setType(CCreatureAnim::EAnimType type)
CCreatureAnimation::CCreatureAnimation(std::string name) : internalFrame(0), once(false)
{
FDef = spriteh->giveFile(name, FILE_ANIMATION); //load main file
//load main file
FDef = CResourceHandler::get()->loadData(
ResourceID(std::string("SPRITES/") + name, EResType::ANIMATION)).first.release();
//init anim data
int i,j, totalInBlock;

View File

@ -1,6 +1,7 @@
#include "StdInc.h"
#include <SDL_image.h>
#include "../lib/Filesystem/CResourceLoader.h"
#include "../lib/CLodHandler.h"
#include "../lib/JsonNode.h"
#include "../lib/vcmi_endian.h"
@ -21,9 +22,6 @@
*
*/
extern DLL_LINKAGE CLodHandler *spriteh;
extern DLL_LINKAGE CLodHandler *bitmaph;
typedef std::map <size_t, std::vector <JsonNode> > source_map;
typedef std::map<size_t, IImage* > image_map;
typedef std::map<size_t, image_map > group_map;
@ -90,8 +88,9 @@ CDefFile::CDefFile(std::string Name):
{ 0, 0, 0, 128},// 50% - shadow body below selection
{ 0, 0, 0, 192} // 75% - shadow border below selection
};
data = CResourceHandler::get()->loadData(
ResourceID(std::string("SPRITES/") + Name, EResType::ANIMATION)).first.release();
data = spriteh->giveFile(Name, FILE_ANIMATION);
palette = new SDL_Color[256];
int it = 0;
@ -936,13 +935,13 @@ void CAnimation::init(CDefFile * file)
source[mapIt->first].resize(mapIt->second);
}
if (spriteh->haveFile(name, FILE_TEXT))
{
int size = 0;
ui8 * configFile = spriteh->giveFile(name, FILE_TEXT, &size);
ResourceID identifier(std::string("SPRITES/") + name, EResType::TEXT);
const JsonNode config((char*)configFile, size);
delete[] configFile;
if (CResourceHandler::get()->existsResource(identifier))
{
auto configFile = CResourceHandler::get()->loadData(identifier);
const JsonNode config((char*)configFile.first.get(), configFile.second);
std::string basepath;
basepath = config["basepath"].String();
@ -977,7 +976,9 @@ void CAnimation::init(CDefFile * file)
CDefFile * CAnimation::getFile() const
{
if (spriteh->haveFile(name, FILE_ANIMATION))
ResourceID identifier(std::string("SPRITES/") + name, EResType::ANIMATION);
if (CResourceHandler::get()->existsResource(identifier))
return new CDefFile(name);
return NULL;
}

View File

@ -1,9 +1,12 @@
#include "StdInc.h"
#include "../lib/Filesystem/CResourceLoader.h"
#include "../lib/Filesystem/CFileInfo.h"
#include "SDL.h"
#include "SDL_image.h"
#include "CBitmapHandler.h"
#include "CDefHandler.h"
#include "UIFramework/SDL_Extensions.h"
#include "../lib/CLodHandler.h"
#include "../lib/vcmi_endian.h"
@ -17,54 +20,37 @@
*
*/
extern DLL_LINKAGE CLodHandler *bitmaph;
extern DLL_LINKAGE CLodHandler *bitmaph_ab;
extern DLL_LINKAGE CLodHandler *spriteh;
void CPCXConv::openPCX(char * PCX, int len)
bool isPCX(const ui8 *header)//check whether file can be PCX according to header
{
pcxs=len;
pcx=(ui8*)PCX;
}
void CPCXConv::fromFile(std::string path)
{
std::ifstream is;
is.open(path.c_str(),std::ios::binary);
is.seekg(0,std::ios::end); // to the end
pcxs = is.tellg(); // read length
is.seekg(0,std::ios::beg); // wracamy na poczatek
pcx = new ui8[pcxs]; // allocate memory
is.read((char*)pcx, pcxs); // read map file to buffer
is.close();
int fSize = read_le_u32(header + 0);
int width = read_le_u32(header + 4);
int height = read_le_u32(header + 8);
return fSize == width*height || fSize == width*height*3;
}
void CPCXConv::saveBMP(std::string path) const
enum Epcxformat
{
std::ofstream os;
os.open(path.c_str(), std::ios::binary);
os.write(reinterpret_cast<const char*>(bmp), bmps);
os.close();
}
PCX8B,
PCX24B
};
SDL_Surface * CPCXConv::getSurface() const
SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
{
SDL_Surface * ret;
int width = -1, height = -1;
Epcxformat format;
int fSize;
int it=0;
fSize = read_le_u32(pcx + it); it+=4;
width = read_le_u32(pcx + it); it+=4;
height = read_le_u32(pcx + it); it+=4;
ui32 fSize = read_le_u32(pcx + it); it+=4;
ui32 width = read_le_u32(pcx + it); it+=4;
ui32 height = read_le_u32(pcx + it); it+=4;
if (fSize==width*height*3)
format=PCX24B;
else if (fSize==width*height)
format=PCX8B;
else
return NULL;
else
return nullptr;
if (format==PCX8B)
{
@ -77,31 +63,23 @@ SDL_Surface * CPCXConv::getSurface() const
it+= width;
}
it = pcxs-256*3;
//palette - last 256*3 bytes
it = size-256*3;
for (int i=0;i<256;i++)
{
SDL_Color tp;
tp.r = pcx[it++];
tp.g = pcx[it++];
tp.b = pcx[it++];
tp.unused = 255;
tp.unused = SDL_ALPHA_OPAQUE;
ret->format->palette->colors[i] = tp;
}
}
else
{
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
int bmask = 0xff0000;
int gmask = 0x00ff00;
int rmask = 0x0000ff;
#else
int bmask = 0x0000ff;
int gmask = 0x00ff00;
int rmask = 0xff0000;
#endif
ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, rmask, gmask, bmask, 0);
ret = CSDL_Ext::createSurfaceWithBpp<3>(width, height);
it = 0xC;
//it == 0xC;
for (int i=0; i<height; i++)
{
memcpy((char*)ret->pixels + ret->pitch * i, pcx + it, width*3);
@ -112,64 +90,51 @@ SDL_Surface * CPCXConv::getSurface() const
return ret;
}
bool isPCX(const ui8 *header)//check whether file can be PCX according to 1st 12 bytes
{
int fSize = read_le_u32(header + 0);
int width = read_le_u32(header + 4);
int height = read_le_u32(header + 8);
return fSize == width*height || fSize == width*height*3;
}
SDL_Surface * BitmapHandler::loadBitmapFromLod(CLodHandler *lod, std::string fname, bool setKey)
SDL_Surface * BitmapHandler::loadBitmapFromDir(std::string path, std::string fname, bool setKey)
{
if(!fname.size())
{
tlog2 << "Call to loadBitmap with void fname!\n";
return NULL;
}
if (!lod->haveFile(fname, FILE_GRAPHICS))
if (!CResourceHandler::get()->existsResource(ResourceID(path + fname, EResType::IMAGE)))
{
//it is possible that this image will be found in another lod archive. Disabling this warning
//tlog2<<"Entry for file "<<fname<<" was not found"<<std::endl;
return NULL;
return nullptr;
}
SDL_Surface * ret=NULL;
int size;
ui8 * file = 0;
file = lod->giveFile(fname, FILE_GRAPHICS, &size);
auto readFile = CResourceHandler::get()->loadData(
ResourceID(path + fname, EResType::IMAGE));
if (isPCX(file))
if (isPCX(readFile.first.get()))
{//H3-style PCX
CPCXConv cp;
cp.openPCX((char*)file,size);
ret = cp.getSurface();
if (!ret)
tlog1<<"Failed to open "<<fname<<" as H3 PCX!\n";
if(ret->format->BytesPerPixel == 1 && setKey)
ret = loadH3PCX(readFile.first.get(), readFile.second);
if (ret)
{
const SDL_Color &c = ret->format->palette->colors[0];
SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format, c.r, c.g, c.b));
if(ret->format->BytesPerPixel == 1 && setKey)
{
const SDL_Color &c = ret->format->palette->colors[0];
SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format, c.r, c.g, c.b));
}
}
else
tlog1<<"Failed to open "<<fname<<" as H3 PCX!\n";
}
else
{ //loading via SDL_Image
std::string filename = lod->getFileName(fname, FILE_GRAPHICS);
std::string ext;
lod->convertName(filename, &ext);
CFileInfo info(CResourceHandler::get()->getResourceName(ResourceID(path + fname, EResType::IMAGE)));
if (ext == ".TGA")//Special case - targa can't be loaded by IMG_Load_RW (no magic constants in header)
{
SDL_RWops *rw = SDL_RWFromMem((void*)file, size);
ret = IMG_LoadTGA_RW( rw );
SDL_FreeRW(rw);
}
else
ret = IMG_Load_RW( SDL_RWFromMem((void*)file, size), 1);
ret = IMG_LoadTyped_RW(
//create SDL_RW with our data (will be deleted by SDL)
SDL_RWFromConstMem((void*)readFile.first.release(), readFile.second),
1, // mark it for auto-deleting
&info.getExtension()[0] + 1); //pass extension without dot (+1 character)
if (!ret)
tlog1<<"Failed to open "<<fname<<" via SDL_Image\n";
delete [] file;
if (ret->format->palette)
{
//set correct value for alpha\unused channel
@ -184,9 +149,8 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey)
{
SDL_Surface *bitmap;
if (!(bitmap = loadBitmapFromLod(bitmaph, fname, setKey)) &&
!(bitmap = loadBitmapFromLod(bitmaph_ab, fname, setKey)) &&
!(bitmap = loadBitmapFromLod(spriteh, fname, setKey)))
if (!(bitmap = loadBitmapFromDir("DATA/", fname, setKey)) &&
!(bitmap = loadBitmapFromDir("SPRITES/", fname, setKey)))
tlog0<<"Error: Failed to find file "<<fname<<"\n";
return bitmap;

View File

@ -3,7 +3,6 @@
struct SDL_Surface;
class CLodHandler;
/*
* CBitmapHandler.h, part of VCMI engine
@ -15,39 +14,17 @@ class CLodHandler;
*
*/
enum Epcxformat {PCX8B, PCX24B};
/// Struct which stands for a simple rgba palette
struct BMPPalette
{
ui8 R,G,B,F;
};
/// Class which converts pcx to bmp images
class CPCXConv
{
public:
ui8 * pcx, *bmp;
int pcxs, bmps;
void fromFile(std::string path);
void saveBMP(std::string path) const;
void openPCX(char * PCX, int len);
SDL_Surface * getSurface() const; //for standard H3 PCX
//SDL_Surface * getSurfaceZ(); //for ZSoft PCX
CPCXConv() //c-tor
: pcx(NULL), bmp(NULL), pcxs(0), bmps(0)
{}
~CPCXConv() //d-tor
{
if (pcxs) delete[] pcx;
if (bmps) delete[] bmp;
}
};
namespace BitmapHandler
{
SDL_Surface * loadH3PCX(ui8 * data, size_t size);
//Load file from specific LOD
SDL_Surface * loadBitmapFromLod(CLodHandler *lod, std::string fname, bool setKey=true);
SDL_Surface * loadBitmapFromDir(std::string path, std::string fname, bool setKey=true);
//Load file from any LODs
SDL_Surface * loadBitmap(std::string fname, bool setKey=true);
};

View File

@ -2,6 +2,7 @@
#include "SDL.h"
#include "CDefHandler.h"
#include "../lib/Filesystem/CResourceLoader.h"
#include "../lib/CLodHandler.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/vcmi_endian.h"
@ -363,7 +364,8 @@ CDefEssential * CDefHandler::essentialize()
CDefHandler * CDefHandler::giveDef(const std::string & defName)
{
ui8 * data = spriteh->giveFile(defName, FILE_ANIMATION);
ui8 * data = CResourceHandler::get()->loadData(
ResourceID(std::string("SPRITES/") + defName, EResType::ANIMATION)).first.release();
if(!data)
throw std::runtime_error("bad def name!");
CDefHandler * nh = new CDefHandler();

View File

@ -7,6 +7,7 @@
#include "CGameInfo.h"
#include "mapHandler.h"
#include "../lib/Filesystem/CResourceLoader.h"
#include "CPreGame.h"
#include "CCastleInterface.h"
#include "../lib/CConsoleHandler.h"
@ -476,16 +477,25 @@ void processCommand(const std::string &message)
}*/
else if(message=="get txt")
{
tlog0<<"Command accepted.\t";
boost::filesystem::create_directory("Extracted_txts");
tlog0<<"Command accepted. Opening .lod file...\t";
CLodHandler * txth = new CLodHandler;
txth->init(GameConstants::DATA_DIR + "/Data/H3bitmap.lod","");
tlog0<<"done.\nScanning .lod file\n";
auto iterator = CResourceHandler::get()->getIterator([](const ResourceID & ident)
{
return ident.getType() == EResType::TEXT && boost::algorithm::starts_with(ident.getName(), "DATA/");
});
BOOST_FOREACH(Entry e, txth->entries)
if( e.type == FILE_TEXT )
txth->extractFile(std::string(GVCMIDirs.UserPath + "/Extracted_txts/")+e.name, e.name, FILE_TEXT);
tlog0<<"\rExtracting done :)\n";
std::string basePath = CResourceHandler::get()->getResourceName(std::string("DATA")) + "/Extracted_txts/";
while (iterator.hasNext())
{
std::ofstream file(basePath + iterator->getName() + ".TXT");
auto text = CResourceHandler::get()->loadData(*iterator);
file.write((char*)text.first.get(), text.second);
++iterator;
}
tlog0 << "\rExtracting done :)\n";
tlog0 << " Extracted files can be found in " << basePath << " directory\n";
}
else if(cn=="crash")
{

View File

@ -1,7 +1,10 @@
#include "StdInc.h"
#include "CPreGame.h"
#include <zlib.h>
#include "../lib/Filesystem/CResourceLoader.h"
#include "../lib/Filesystem/CFileInfo.h"
#include "../lib/Filesystem/CCompressedStream.h"
#include "../lib/CStopWatch.h"
#include "UIFramework/SDL_Extensions.h"
#include "CGameInfo.h"
@ -385,7 +388,8 @@ CreditsScreen::CreditsScreen()
OBJ_CONSTRUCTION_CAPTURING_ALL;
pos.w = CGP->menu->pos.w;
pos.h = CGP->menu->pos.h;
std::string text = bitmaph->getTextFile("CREDITS");
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/CREDITS.TXT"));
std::string text((char*)textFile.first.get(), textFile.second);
size_t firstQuote = text.find('\"')+1;
text = text.substr(firstQuote, text.find('\"', firstQuote) - firstQuote );
credits = new CTextBox(text, Rect(pos.w - 350, 600, 350, 32000), 0, FONT_CREDITS, CENTER, Colors::Cornsilk);
@ -767,7 +771,7 @@ void CSelectionScreen::changeSelection( const CMapInfo *to )
SEL->sInfo.difficulty = to->scenarioOpts->difficulty;
if(screenType != CMenuScreen::campaignList)
{
updateStartInfo(to ? to->filename : "", sInfo, to ? to->mapHeader : NULL);
updateStartInfo(to ? to->fileURI : "", sInfo, to ? to->mapHeader : NULL);
}
card->changeSelection(to);
if(screenType != CMenuScreen::campaignList)
@ -789,7 +793,7 @@ void CSelectionScreen::startCampaign()
{
if (SEL->current)
{
CCampaign * ourCampaign = CCampaignHandler::getCampaign(SEL->current->filename, SEL->current->lodCmpgn);
CCampaign * ourCampaign = CCampaignHandler::getCampaign(SEL->current->fileURI);
CCampaignState * campState = new CCampaignState();
campState->camp = ourCampaign;
GH.pushInt( new CBonusSelection(campState) );
@ -1021,42 +1025,56 @@ void SelectionTab::filter( int size, bool selectFirst )
}
}
void SelectionTab::getFiles(std::vector<FileInfo> &out, const std::string &dirname, const std::string &ext)
std::vector<ResourceID> SelectionTab::getFiles(std::string dirURI, int resType)
{
CFileUtility::getFilesWithExt(out, dirname, ext);
allItems.resize(out.size());
std::vector<ResourceID> ret;
boost::to_upper(dirURI);
auto iterator = CResourceHandler::get()->getIterator([&](const ResourceID & ident)
{
return ident.getType() == resType
&& boost::algorithm::starts_with(ident.getName(), dirURI);
});
while (iterator.hasNext())
{
ret.push_back(*iterator);
++iterator;
}
allItems.resize(ret.size());
return ret;
}
void SelectionTab::parseMaps(std::vector<FileInfo> &files, int start, int threads)
void SelectionTab::parseMaps(const std::vector<ResourceID> &files, int start, int threads)
{
int read=0;
ui8 mapBuffer[1500];
while(start < allItems.size())
{
gzFile tempf = gzopen(files[start].name.c_str(),"rb");
read = gzread(tempf, mapBuffer, 1500);
gzclose(tempf);
auto compressed = CResourceHandler::get()->load(files[start]);
CCompressedStream stream(compressed, true);
int read = stream.read(mapBuffer, 1500);
if(read < 50 || !mapBuffer[4])
{
tlog3 << "\t\tWarning: corrupted map file: " << files[start].name << std::endl;
tlog3 << "\t\tWarning: corrupted map file: " << files[start].getName() << std::endl;
}
else //valid map
{
allItems[start].mapInit(files[start].name, mapBuffer);
//allItems[start].date = "DATEDATE";// files[start].date;
allItems[start].mapInit(files[start].getName(), mapBuffer);
}
start += threads;
}
}
void SelectionTab::parseGames(std::vector<FileInfo> &files, bool multi)
void SelectionTab::parseGames(const std::vector<ResourceID> &files, bool multi)
{
for(int i=0; i<files.size(); i++)
{
try
{
CLoadFile lf(files[i].name);
CLoadFile lf(CResourceHandler::get()->getResourceName(files[i]));
ui8 sign[8];
lf >> sign;
@ -1065,9 +1083,10 @@ void SelectionTab::parseGames(std::vector<FileInfo> &files, bool multi)
allItems[i].mapHeader = new CMapHeader();
lf >> *(allItems[i].mapHeader) >> allItems[i].scenarioOpts;
allItems[i].filename = files[i].name;
allItems[i].fileURI = files[i].getName();
allItems[i].countPlayers();
allItems[i].date = std::asctime(std::localtime(&files[i].date));
std::time_t time = CFileInfo(CResourceHandler::get()->getResourceName(files[i])).getDate();
allItems[i].date = std::asctime(std::localtime(&time));
if((allItems[i].actualHumanPlayers > 1) != multi) //if multi mode then only multi games, otherwise single
{
@ -1077,18 +1096,17 @@ void SelectionTab::parseGames(std::vector<FileInfo> &files, bool multi)
catch(std::exception &e)
{
vstd::clear_pointer(allItems[i].mapHeader);
tlog3 << "Failed to process " << files[i].name <<": " << e.what() << std::endl;
tlog3 << "Failed to process " << files[i].getName() <<": " << e.what() << std::endl;
}
}
}
void SelectionTab::parseCampaigns( std::vector<FileInfo> & files )
void SelectionTab::parseCampaigns(const std::vector<ResourceID> & files )
{
for(int i=0; i<files.size(); i++)
{
//allItems[i].date = std::asctime(std::localtime(&files[i].date));
allItems[i].filename = files[i].name;
allItems[i].lodCmpgn = files[i].inLod;
allItems[i].fileURI = files[i].getName();
allItems[i].campaignInit();
}
}
@ -1122,25 +1140,17 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
}
else
{
std::vector<FileInfo> toParse;
std::vector<CCampaignHeader> cpm;
switch(tabType)
{
case CMenuScreen::newGame:
getFiles(toParse, GameConstants::DATA_DIR + "/Maps", "h3m"); //get all maps
/* Load maps from user directory too, unless it is also the
* same as the data directory (as is the case on
* windows). */
if (GVCMIDirs.UserPath != GameConstants::DATA_DIR)
getFiles(toParse, GVCMIDirs.UserPath + "/Maps", "h3m"); //get all maps
parseMaps(toParse);
parseMaps(getFiles("Maps/", EResType::MAP));
positions = 18;
break;
case CMenuScreen::loadGame:
case CMenuScreen::saveGame:
getFiles(toParse, GVCMIDirs.UserPath + "/Games", "vlgm1"); //get all saves
parseGames(toParse, MultiPlayer);
parseGames(getFiles("Saves/", EResType::LIB_SAVEGAME), MultiPlayer);
if(tabType == CMenuScreen::loadGame)
{
positions = 18;
@ -1155,32 +1165,9 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
txt->filters.add(CTextInput::filenameFilter);
}
break;
case CMenuScreen::campaignList:
getFiles(toParse, GameConstants::DATA_DIR + "/Maps", "h3c"); //get all campaigns
/* Load campaingns from user directory too, unless it is also the
* same as the data directory (as is the case on
* windows). */
if (GVCMIDirs.UserPath != GameConstants::DATA_DIR)
getFiles(toParse, GVCMIDirs.UserPath + "/Maps", "h3c"); //get all maps
for (int g=0; g<toParse.size(); ++g)
{
toParse[g].inLod = false;
}
//add lod cmpgns
cpm = CCampaignHandler::getCampaignHeaders(CCampaignHandler::Custom);
for (int g = 0; g < cpm.size(); g++)
{
FileInfo fi;
fi.inLod = cpm[g].loadFromLod;
fi.name = cpm[g].filename;
if (cpm[g].loadFromLod)
{
toParse.push_back(fi);
allItems.push_back(CMapInfo(false));
}
}
parseCampaigns(toParse);
case CMenuScreen::campaignList:
parseCampaigns(getFiles("Maps/", EResType::CAMPAIGN));
positions = 18;
break;
@ -1229,7 +1216,7 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
switch(tabType)
{
case CMenuScreen::newGame:
selectFName(GameConstants::DATA_DIR + "/Maps/Arrogance.h3m");
selectFName("Maps/Arrogance");
break;
case CMenuScreen::loadGame:
case CMenuScreen::campaignList:
@ -1296,7 +1283,11 @@ void SelectionTab::select( int position )
slider->moveTo(slider->value + position - positions + 1);
if(txt)
txt->setTxt(fs::basename(curItems[py]->filename));
{
std::string filename = CResourceHandler::get()->getResourceName(
ResourceID(curItems[py]->fileURI, EResType::MAP));
txt->setTxt(CFileInfo(filename).getBaseName());
}
onSelect(curItems[py]);
}
@ -1348,7 +1339,7 @@ void SelectionTab::printMaps(SDL_Surface *to)
{
//amount of players
std::ostringstream ostr(std::ostringstream::out);
ostr << currentItem->playerAmnt << "/" << currentItem->humenPlayers;
ostr << currentItem->playerAmnt << "/" << currentItem->humanPlayers;
CSDL_Ext::printAt(ostr.str(), POS(29, 120), FONT_SMALL, itemColor, to);
//map size
@ -1387,7 +1378,7 @@ void SelectionTab::printMaps(SDL_Surface *to)
break;
default:
// Unknown version. Be safe and ignore that map
tlog2 << "Warning: " << currentItem->filename << " has wrong version!\n";
tlog2 << "Warning: " << currentItem->fileURI << " has wrong version!\n";
continue;
}
blitAt(format->ourImages[temp].bitmap, POS(88, 117), to);
@ -1427,7 +1418,7 @@ void SelectionTab::printMaps(SDL_Surface *to)
}
else
{
name = fs::basename(currentItem->filename);
name = fs::basename(currentItem->fileURI);
}
//print name
@ -1528,11 +1519,12 @@ int SelectionTab::getLine()
return line;
}
void SelectionTab::selectFName( const std::string &fname )
void SelectionTab::selectFName( std::string fname )
{
boost::to_upper(fname);
for(int i = curItems.size() - 1; i >= 0; i--)
{
if(curItems[i]->filename == fname)
if(curItems[i]->fileURI == fname)
{
slider->moveTo(i);
selectAbs(i);
@ -3553,7 +3545,7 @@ CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode &config )
status = config["open"].Bool() ? CCampaignScreen::ENABLED : CCampaignScreen::DISABLED;
CCampaignHeader header = CCampaignHandler::getHeader(campFile, true);
CCampaignHeader header = CCampaignHandler::getHeader(campFile);
hoverText = header.name;
if (status != CCampaignScreen::DISABLED)
@ -3571,11 +3563,15 @@ CCampaignScreen::CCampaignButton::CCampaignButton(const JsonNode &config )
void CCampaignScreen::CCampaignButton::clickLeft(tribool down, bool previousState)
{
// Campaign screen is broken. Disabled for now
return;
if (down)
{
// Close running video and open the selected campaign
CCS->videoh->close();
CCampaign * ourCampaign = CCampaignHandler::getCampaign(campFile, true);
CCampaign * ourCampaign = CCampaignHandler::getCampaign(campFile);
CCampaignState * campState = new CCampaignState();
campState->camp = ourCampaign;
GH.pushInt( new CBonusSelection(campState) );

View File

@ -1,6 +1,6 @@
#pragma once
#include "../lib/Filesystem/CResourceLoader.h"
#include <SDL.h>
#include "../lib/StartInfo.h"
#include "GUIClasses.h"
@ -143,10 +143,10 @@ class SelectionTab : public CIntObject
private:
CDefHandler *format; //map size
void parseMaps(std::vector<FileInfo> &files, int start = 0, int threads = 1);
void parseGames(std::vector<FileInfo> &files, bool multi);
void parseCampaigns( std::vector<FileInfo> & files );
void getFiles(std::vector<FileInfo> &out, const std::string &dirname, const std::string &ext);
void parseMaps(const std::vector<ResourceID> &files, int start = 0, int threads = 1);
void parseGames(const std::vector<ResourceID> &files, bool multi);
void parseCampaigns(const std::vector<ResourceID> & files );
std::vector<ResourceID> getFiles(std::string dirURI, int resType);
CMenuScreen::EState tabType;
public:
int positions; //how many entries (games/maps) can be shown
@ -172,7 +172,7 @@ public:
void sort();
void printMaps(SDL_Surface *to);
int getLine();
void selectFName(const std::string &fname);
void selectFName(std::string fname);
void showAll(SDL_Surface * to);
void clickLeft(tribool down, bool previousState);

View File

@ -236,7 +236,7 @@ void CClient::loadGame( const std::string & fname )
const_cast<CGameInfo*>(CGI)->mh = new CMapHandler();
StartInfo *si;
CLoadFile lf(fname + ".vlgm1");
CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::LIB_SAVEGAME)));
lf >> sig >> dum >> si;
tlog0 <<"Reading save signature: "<<tmh.getDiff()<<std::endl;
@ -277,7 +277,7 @@ void CClient::loadGame( const std::string & fname )
tlog0 <<"Sent info to server: "<<tmh.getDiff()<<std::endl;
{
CLoadFile lf(fname + ".vcgm1");
CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::CLIENT_SAVEGAME)));
lf >> *this;
}
}

View File

@ -1,6 +1,7 @@
#include "StdInc.h"
#include "Graphics.h"
#include "../lib/Filesystem/CResourceLoader.h"
#include "CDefHandler.h"
#include "UIFramework/SDL_Extensions.h"
#include <SDL_ttf.h>
@ -45,7 +46,9 @@ Graphics * graphics = NULL;
void Graphics::loadPaletteAndColors()
{
std::string pals = bitmaph->getTextFile("PLAYERS.PAL", FILE_OTHER);
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/PLAYERS.PAL"));
std::string pals((char*)textFile.first.get(), textFile.second);
playerColorPalette = new SDL_Color[256];
neutralColor = new SDL_Color;
playerColors = new SDL_Color[GameConstants::PLAYER_LIMIT];
@ -518,22 +521,17 @@ void Graphics::loadTrueType()
Font * Graphics::loadFont( const char * name )
{
int len = 0;
ui8 * hlp = bitmaph->giveFile(name, FILE_FONT, &len);
if(!hlp || !len)
ui8 * hlp = CResourceHandler::get()->loadData(
ResourceID(std::string("DATA/") + name, EResType::FONT)).first.release();
if(!hlp)
{
tlog1 << "Error: cannot load font: " << name << std::endl;
return NULL;
}
int magic = SDL_SwapLE32(*(const Uint32*)hlp);
if(len < 10000 || (magic != 589598 && magic != 589599))
{
tlog1 << "Suspicious font file (length " << len <<", fname " << name << "), logging to suspicious_" << name << ".fnt\n";
std::string suspFName = "suspicious_" + std::string(name) + ".fnt";
std::ofstream o(suspFName.c_str());
o.write((const char*)hlp, len);
}
if(magic != 589598 && magic != 589599)
tlog1 << "Suspicious font file, fname " << name << "n";
Font *ret = new Font(hlp);
return ret;

62
config/filesystem.json Normal file
View File

@ -0,0 +1,62 @@
{
// Complete filesystem available after initialization
// All paths and names here are case-insensitive
// If same filename is found twice entry from latest source will be used
// path can start from:
// "GLOBAL" - global location for data files. /usr/share/vcmi | C:\Program files\Heroes 3\
// "LOCAL" - local user-specific files. ~/.vcmi | same as global (TODO: move it to C:\Users\whatever)
// "ALL" - will check local directory first or (if was not found) in global directory
// NOTE: this file must be available as "ALL/config/filesystem.json"
"filesystem":
{
"DATA/" :
[
{"type" : "file", "path" : "ALL/Data/H3ab_bmp.lod"},
{"type" : "file", "path" : "ALL/Data/H3bitmap.lod"},
{"type" : "dir", "path" : "GLOBAL/Data"},
{"type" : "dir", "path" : "LOCAL/Data"}
],
"SPRITES/":
[
{"type" : "file", "path" : "ALL/Data/H3ab_spr.lod"},
{"type" : "file", "path" : "ALL/Data/H3sprite.lod"},
{"type" : "dir", "path" : "GLOBAL/Sprites"},
{"type" : "dir", "path" : "LOCAL/Sprites"}
],
"SOUNDS/":
[
{"type" : "file", "path" : "ALL/Data/H3ab_ahd.snd"},
{"type" : "file", "path" : "ALL/Data/Heroes3.snd"},
//WoG have overriden sounds with .82m extension in Data
{"type" : "dir", "path" : "GLOBAL/Data"},
{"type" : "dir", "path" : "LOCAL/Data"}
],
"MUSIC/":
[
{"type" : "dir", "path" : "GLOBAL/Mp3"},
{"type" : "dir", "path" : "LOCAL/Mp3"}
],
"VIDEO/":
[
{"type" : "file", "path" : "ALL/Data/H3ab_ahd.vid"},
{"type" : "file", "path" : "ALL/Data/H3ab_ahd.vid"},
// Location of video files in linux release
{"type" : "dir", "path" : "GLOBAL/Data/Video"},
{"type" : "dir", "path" : "LOCAL/Data/Video"}
],
"CONFIG/":
[
{"type" : "dir", "path" : "GLOBAL/Config"},
{"type" : "dir", "path" : "LOCAL/Config"}
],
"MAPS/":
[
{"type" : "dir", "path" : "GLOBAL/Maps"},
{"type" : "dir", "path" : "LOCAL/Maps"}
],
"SAVES/":
[
{"type" : "dir", "path" : "LOCAL/Games"},
]
}
}

View File

@ -65,13 +65,13 @@
"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN", "hotkey" : 27},
"items":
[
{ "x":90, "y":72, "file":"GOOD1.H3C", "image":"CAMPGD1S", "video":"CGOOD1", "open": true },
{ "x":539, "y":72, "file":"EVIL1.H3C", "image":"CAMPEV1S", "video":"CEVIL1", "open": true },
{ "x":43, "y":245, "file":"GOOD2.H3C", "image":"CAMPGD2S", "video":"CGOOD2", "open": true },
{ "x":313, "y":244, "file":"NEUTRAL.H3C", "image":"CAMPNEUS", "video":"CNEUTRAL", "open": true },
{ "x":586, "y":246, "file":"EVIL2.H3C", "image":"CAMPEV2S", "video":"CEVIL2", "open": true },
{ "x":34, "y":417, "file":"GOOD3.H3C", "image":"CAMPGD3S", "video":"CGOOD3", "open": true },
{ "x":404, "y":414, "file":"SECRET.H3C", "image":"CAMPSCTS", "video":"CSECRET", "open": true }
{ "x":90, "y":72, "file":"DATA/GOOD1.H3C", "image":"CAMPGD1S", "video":"CGOOD1", "open": true },
{ "x":539, "y":72, "file":"DATA/EVIL1.H3C", "image":"CAMPEV1S", "video":"CEVIL1", "open": true },
{ "x":43, "y":245, "file":"DATA/GOOD2.H3C", "image":"CAMPGD2S", "video":"CGOOD2", "open": true },
{ "x":313, "y":244, "file":"DATA/NEUTRAL.H3C", "image":"CAMPNEUS", "video":"CNEUTRAL", "open": true },
{ "x":586, "y":246, "file":"DATA/EVIL2.H3C", "image":"CAMPEV2S", "video":"CEVIL2", "open": true },
{ "x":34, "y":417, "file":"DATA/GOOD3.H3C", "image":"CAMPGD3S", "video":"CGOOD3", "open": true },
{ "x":404, "y":414, "file":"DATA/SECRET.H3C", "image":"CAMPSCTS", "video":"CSECRET", "open": true }
]
},
{
@ -85,12 +85,12 @@
"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN", "hotkey" : 27},
"items":
[
{ "x":90, "y":72, "file":"AB.H3C", "image":"CAMP1AB7", "video":"C1ab7", "open": true },
{ "x":539, "y":72, "file":"BLOOD.H3C", "image":"CAMP1DB2", "video":"C1db2", "open": true },
{ "x":43, "y":245, "file":"SLAYER.H3C", "image":"CAMP1DS1", "video":"C1ds1", "open": true },
{ "x":313, "y":244, "file":"FESTIVAL.H3C", "image":"CAMP1FL3", "video":"C1fl3", "open": true },
{ "x":586, "y":246, "file":"FIRE.H3C", "image":"CAMP1PF2", "video":"C1pf2", "open": true },
{ "x":34, "y":417, "file":"FOOL.H3C", "image":"CAMP1FW1", "video":"C1fw1", "open": true }
{ "x":90, "y":72, "file":"DATA/AB.H3C", "image":"CAMP1AB7", "video":"C1ab7", "open": true },
{ "x":539, "y":72, "file":"DATA/BLOOD.H3C", "image":"CAMP1DB2", "video":"C1db2", "open": true },
{ "x":43, "y":245, "file":"DATA/SLAYER.H3C", "image":"CAMP1DS1", "video":"C1ds1", "open": true },
{ "x":313, "y":244, "file":"DATA/FESTIVAL.H3C", "image":"CAMP1FL3", "video":"C1fl3", "open": true },
{ "x":586, "y":246, "file":"DATA/FIRE.H3C", "image":"CAMP1PF2", "video":"C1pf2", "open": true },
{ "x":34, "y":417, "file":"DATA/FOOL.H3C", "image":"CAMP1FW1", "video":"C1fw1", "open": true }
]
},
@ -100,13 +100,13 @@
"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN", "hotkey" : 27},
"items":
[
{ "x":90, "y":72, "file":"GEM.H3C", "image":"CAMPNB1", "video":"NEW", "open": true },
{ "x":539, "y":72, "file":"GELU.H3C", "image":"CAMPEL1", "video":"ELIXIR", "open": true },
{ "x":43, "y":245, "file":"CRAG.H3C", "image":"CAMPHS1", "video":"HACK", "open": true },
{ "x":313, "y":244, "file":"SANDRO.H3C", "image":"CAMPRN1", "video":"RISE", "open": true },
{ "x":586, "y":246, "file":"YOG.H3C", "image":"CAMPBB1", "video":"BIRTH", "open": true },
{ "x":34, "y":417, "file":"FINAL.H3C", "image":"CAMPUA1", "video":"UNHOLY", "open": true },
{ "x":404, "y":414, "file":"SECRET1.H3C", "image":"CAMPSP1", "video":"SPECTRE", "open": true }
{ "x":90, "y":72, "file":"DATA/GEM.H3C", "image":"CAMPNB1", "video":"NEW", "open": true },
{ "x":539, "y":72, "file":"DATA/GELU.H3C", "image":"CAMPEL1", "video":"ELIXIR", "open": true },
{ "x":43, "y":245, "file":"DATA/CRAG.H3C", "image":"CAMPHS1", "video":"HACK", "open": true },
{ "x":313, "y":244, "file":"DATA/SANDRO.H3C", "image":"CAMPRN1", "video":"RISE", "open": true },
{ "x":586, "y":246, "file":"DATA/YOG.H3C", "image":"CAMPBB1", "video":"BIRTH", "open": true },
{ "x":34, "y":417, "file":"DATA/FINAL.H3C", "image":"CAMPUA1", "video":"UNHOLY", "open": true },
{ "x":404, "y":414, "file":"DATA/SECRET1.H3C", "image":"CAMPSP1", "video":"SPECTRE", "open": true }
]
},
@ -116,10 +116,10 @@
"exitbutton" : {"x": 658, "y": 482, "name":"CMPSCAN", "hotkey" : 27},
"items":
[
{ "x":90, "y":72, "file":"ZC1.H3C", "image":"CAMPZ01", "open": true},
{ "x":539, "y":72, "file":"ZC2.H3C", "image":"CAMPZ02", "open": true},
{ "x":43, "y":245, "file":"ZC3.H3C", "image":"CAMPZ03", "open": true},
{ "x":311, "y":242, "file":"ZC4.H3C", "image":"CAMPZ04", "open": true}
{ "x":90, "y":72, "file":"DATA/ZC1.H3C", "image":"CAMPZ01", "open": true},
{ "x":539, "y":72, "file":"DATA/ZC2.H3C", "image":"CAMPZ02", "open": true},
{ "x":43, "y":245, "file":"DATA/ZC3.H3C", "image":"CAMPZ03", "open": true},
{ "x":311, "y":242, "file":"DATA/ZC4.H3C", "image":"CAMPZ04", "open": true}
]
}

View File

@ -1,16 +1,16 @@
#include "StdInc.h"
#include "CArtHandler.h"
#include "Filesystem/CResourceLoader.h"
#include "CLodHandler.h"
#include "CGeneralTextHandler.h"
#include <boost/random/linear_congruential.hpp>
#include "../lib/VCMI_Lib.h"
#include "VCMI_Lib.h"
#include "CSpellHandler.h"
#include "CObjectHandler.h"
#include "NetPacks.h"
#include "../lib/JsonNode.h"
#include "JsonNode.h"
extern CLodHandler *bitmaph;
using namespace boost::assign;
/*
@ -239,7 +239,10 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
growingArtifacts += 146, 147, 148, 150, 151, 152, 153;
static std::map<char, CArtifact::EartClass> classes =
map_list_of('S',CArtifact::ART_SPECIAL)('T',CArtifact::ART_TREASURE)('N',CArtifact::ART_MINOR)('J',CArtifact::ART_MAJOR)('R',CArtifact::ART_RELIC);
std::string buf = bitmaph->getTextFile("ARTRAITS.TXT"), dump, pom;
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/ARTRAITS.TXT"));
std::string buf((char*)textFile.first.get(), textFile.second);
std::string dump, pom;
int it=0;
for(int i=0; i<2; ++i)
{

View File

@ -3,12 +3,11 @@
#include "CGeneralTextHandler.h"
#include "CLodHandler.h"
#include "../lib/Filesystem/CResourceLoader.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/JsonNode.h"
#include "GameConstants.h"
extern CLodHandler * bitmaph;
/*
* CBuildingHandler.cpp, part of VCMI engine
*
@ -44,7 +43,10 @@ static CBuilding * readBg(std::string &buf, int& it)
}
void CBuildingHandler::loadBuildings()
{
std::string buf = bitmaph->getTextFile("BUILDING.TXT"), temp;
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/BUILDING.TXT"));
std::string buf((char*)textFile.first.get(), textFile.second);
std::string temp;
int it=0; //buf iterator
temp = readTo(buf,it,'\n');temp = readTo(buf,it,'\n');//read 2 lines of file info

View File

@ -1,6 +1,8 @@
#include "StdInc.h"
#include "CCampaignHandler.h"
#include "Filesystem/CResourceLoader.h"
#include "Filesystem/CCompressedStream.h"
#include "CLodHandler.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/vcmi_endian.h"
@ -35,7 +37,7 @@ std::vector<CCampaignHeader> CCampaignHandler::getCampaignHeaders(GetMode mode)
tlog1 << "Cannot find " << dirname << " directory!\n";
}
if (mode == Custom || mode == ALL) //add custom campaigns
if (mode == Custom) //add custom campaigns
{
fs::path tie(dirname);
fs::directory_iterator end_iter;
@ -44,51 +46,38 @@ std::vector<CCampaignHeader> CCampaignHandler::getCampaignHeaders(GetMode mode)
if(fs::is_regular_file(file->status())
&& boost::ends_with(file->path().filename().string(), ext))
{
ret.push_back( getHeader( file->path().string(), false ) );
ret.push_back( getHeader( file->path().string()) );
}
}
}
if (mode == ALL) //add all lod campaigns
{
BOOST_FOREACH(Entry e, bitmaph->entries)
{
if( e.type == FILE_CAMPAIGN )
{
ret.push_back( getHeader(e.name, true) );
}
}
}
return ret;
}
CCampaignHeader CCampaignHandler::getHeader( const std::string & name, bool fromLod )
CCampaignHeader CCampaignHandler::getHeader( const std::string & name)
{
int realSize;
ui8 * cmpgn = getFile(name, fromLod, realSize);
ui8 * cmpgn = getFile(name).first;
int it = 0;//iterator for reading
CCampaignHeader ret = readHeaderFromMemory(cmpgn, it);
ret.filename = name;
ret.loadFromLod = fromLod;
delete [] cmpgn;
return ret;
}
CCampaign * CCampaignHandler::getCampaign( const std::string & name, bool fromLod )
CCampaign * CCampaignHandler::getCampaign( const std::string & name)
{
CCampaign * ret = new CCampaign();
int realSize;
ui8 * cmpgn = getFile(name, fromLod, realSize);
auto file = getFile(name);
int realSize = file.second;
ui8 * cmpgn = file.first;
int it = 0; //iterator for reading
ret->header = readHeaderFromMemory(cmpgn, it);
ret->header.filename = name;
ret->header.loadFromLod = fromLod;
int howManyScenarios = VLC->generaltexth->campaignRegionNames[ret->header.mapVersion].size();
for(int g=0; g<howManyScenarios; ++g)
@ -418,24 +407,15 @@ bool CCampaignHandler::startsAt( const ui8 * buffer, int size, int pos )
return true;
}
ui8 * CCampaignHandler::getFile( const std::string & name, bool fromLod, int & outSize )
std::pair<ui8 *, size_t> CCampaignHandler::getFile(const std::string & name)
{
ui8 * cmpgn = 0;
if(fromLod)
{
if (bitmaph->haveFile(name, FILE_CAMPAIGN))
cmpgn = bitmaph->giveFile(name, FILE_CAMPAIGN, &outSize);
else if (bitmaph_ab->haveFile(name, FILE_CAMPAIGN))
cmpgn = bitmaph_ab->giveFile(name, FILE_CAMPAIGN, &outSize);
else
tlog1 << "Cannot find file: " << name << std::endl;
cmpgn = CLodHandler::getUnpackedData(cmpgn, outSize, &outSize);
}
else
{
cmpgn = CLodHandler::getUnpackedFile(name, &outSize);
}
return cmpgn;
std::unique_ptr<CInputStream> stream = CResourceHandler::get()->load(ResourceID(name, EResType::CAMPAIGN));
stream.reset(new CCompressedStream(stream, true));
ui8 * ret = new ui8[stream->getSize()];
stream->read(ret, stream->getSize());
return std::make_pair(ret, stream->getSize());
}
bool CCampaign::conquerable( int whichScenario ) const
@ -567,10 +547,7 @@ void CCampaignState::initNewCampaign( const StartInfo &si )
campaignName = si.mapname;
currentMap = si.whichMapInCampaign;
//check if campaign is in lod or not
bool inLod = campaignName.find('/') == std::string::npos;
camp = CCampaignHandler::getCampaign(campaignName, inLod); //TODO lod???
camp = CCampaignHandler::getCampaign(campaignName);
for (ui8 i = 0; i < camp->mapPieces.size(); i++)
mapsRemaining.push_back(i);
}

View File

@ -162,11 +162,11 @@ class DLL_LINKAGE CCampaignHandler
static CScenarioTravel readScenarioTravelFromMemory( const ui8 * buffer, int & outIt , int version);
static std::vector<ui32> locateH3mStarts(const ui8 * buffer, int start, int size);
static bool startsAt( const ui8 * buffer, int size, int pos ); //a simple heuristic that checks if a h3m starts at given pos
static ui8 * getFile(const std::string & name, bool fromLod, int & outSize);
static std::pair<ui8 *, size_t> getFile(const std::string & name);
public:
enum GetMode {RoE, AB, SoD, WoG, Custom, ALL};
enum GetMode {RoE, AB, SoD, WoG, Custom};
static std::vector<CCampaignHeader> getCampaignHeaders(GetMode mode);
static CCampaignHeader getHeader( const std::string & name, bool fromLod ); //name - name of appropriate file
static CCampaignHeader getHeader( const std::string & name); //name - name of appropriate file
static CCampaign * getCampaign(const std::string & name, bool fromLod); //name - name of appropriate file
static CCampaign * getCampaign(const std::string & name); //name - name of appropriate file
};

View File

@ -1,6 +1,7 @@
#include "StdInc.h"
#include "CCreatureHandler.h"
#include "Filesystem/CResourceLoader.h"
#include "CLodHandler.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/CGameState.h"
@ -8,7 +9,6 @@
#include "CHeroHandler.h"
using namespace boost::assign;
extern CLodHandler * bitmaph;
/*
* CCreatureHandler.cpp, part of VCMI engine
@ -268,7 +268,8 @@ void CCreatureHandler::loadCreatures()
tlog5 << "\t\tReading config/cr_abils.json and ZCRTRAIT.TXT" << std::endl;
////////////reading ZCRTRAIT.TXT ///////////////////
std::string buf = bitmaph->getTextFile("ZCRTRAIT.TXT");
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/ZCRTRAIT.TXT"));
std::string buf((char*)textFile.first.get(), textFile.second);
int andame = buf.size();
int i=0; //buf iterator
int hmcr=0;
@ -495,7 +496,8 @@ void CCreatureHandler::loadCreatures()
if (GameConstants::STACK_EXP) //reading default stack experience bonuses
{
buf = bitmaph->getTextFile("CREXPBON.TXT");
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/CREXPBON.TXT"));
std::string buf((char*)textFile.first.get(), textFile.second);
int it = 0;
si32 creid = -1;
Bonus b; //prototype with some default properties
@ -570,7 +572,8 @@ void CCreatureHandler::loadCreatures()
}
}
buf = bitmaph->getTextFile("CREXPMOD.TXT"); //could be hardcoded though, lots of useless info
textFile = CResourceHandler::get()->loadData(ResourceID("DATA/CREXPMOD.TXT"));
buf = std::string((char*)textFile.first.get(), textFile.second);
it = 0;
loadToIt (dump2, buf, it, 3); //ignore first line
@ -637,7 +640,8 @@ void CCreatureHandler::loadCreatures()
void CCreatureHandler::loadAnimationInfo()
{
std::string buf = bitmaph->getTextFile("CRANIM.TXT");
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/CRANIM.TXT"));
std::string buf((char*)textFile.first.get(), textFile.second);
int andame = buf.size();
int i=0; //buf iterator
int hmcr=0;

View File

@ -17,7 +17,6 @@
*/
#define ALLCREATURESGETDOUBLEMONTHS false
class CLodHandler;
class CCreatureHandler;
class CCreature;

View File

@ -1,13 +1,12 @@
#include "StdInc.h"
#include "CDefObjInfoHandler.h"
#include "Filesystem/CResourceLoader.h"
#include "../client/CGameInfo.h"
#include "CLodHandler.h"
#include "../lib/VCMI_Lib.h"
#include "GameConstants.h"
extern CLodHandler * bitmaph;
/*
* CDefObjInfoHandler.cpp, part of VCMI engine
*
@ -36,21 +35,24 @@ CGDefInfo::CGDefInfo()
void CGDefInfo::fetchInfoFromMSK()
{
std::string msk = spriteh->getTextFile(name, FILE_MASK);
width = msk[0];
height = msk[1];
auto msk = CResourceHandler::get()->loadData(ResourceID(std::string("SPRITES/") + name, EResType::MASK));
width = msk.first.get()[0];
height = msk.first.get()[1];
for(int i=0; i<6; ++i)
{
coverageMap[i] = msk[i+2];
shadowCoverage[i] = msk[i+8];
coverageMap[i] = msk.first.get()[i+2];
shadowCoverage[i] = msk.first.get()[i+8];
}
}
void CDefObjInfoHandler::load()
{
VLC->dobjinfo = this;
std::istringstream inp(bitmaph->getTextFile("ZOBJCTS.TXT"));
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/ZOBJCTS.TXT"));
std::istringstream inp(std::string((char*)textFile.first.get(), textFile.second));
int objNumber;
inp>>objNumber;
std::string mapStr;

View File

@ -14,7 +14,6 @@
*/
class CDefEssential;
class CLodHandler;
class DLL_LINKAGE CGDefInfo
{
public:

View File

@ -11,7 +11,7 @@
*
*/
/*
namespace fs = boost::filesystem;
CFileUtility::CFileUtility(void)
@ -52,4 +52,4 @@ void CFileUtility::getFilesWithExt(std::vector<FileInfo> &out, const std::string
}
}
}
}*/

View File

@ -15,11 +15,10 @@
/// Struct which stores name, date and a value which says if the file is located in LOD
struct FileInfo
{
std::string name; // file name with full path and extension
std::string name; // file URI (upper case, no extension)
std::time_t date;
bool inLod; //tells if this file is located in Lod
};
/*
class DLL_LINKAGE CFileUtility
{
public:
@ -28,4 +27,4 @@ public:
static void getFilesWithExt(std::vector<FileInfo> &out, const std::string &dirname, const std::string &ext);
};
*/

View File

@ -20,7 +20,8 @@
#include "RegisterTypes.h"
#include "CMapInfo.h"
#include "BattleState.h"
#include "../lib/JsonNode.h"
#include "JsonNode.h"
#include "Filesystem/CResourceLoader.h"
#include "GameConstants.h"
DLL_LINKAGE boost::rand48 ran;
@ -2814,8 +2815,10 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
assert(ss.heroPrimSkills.empty() || ss.heroPrimSkills.size() == GameConstants::PRIMARY_SKILLS);
if(ss.heroId != -1)
{
BOOST_FOREACH(const JsonNode &spell, n["spells"].Vector())
ss.spells.insert(spell.Float());
}
}
BOOST_FOREACH(const JsonNode &n, duelData["obstacles"].Vector())

View File

@ -1,7 +1,8 @@
#include "StdInc.h"
#include "CGeneralTextHandler.h"
#include "../lib/VCMI_Lib.h"
#include "Filesystem/CResourceLoader.h"
#include "VCMI_Lib.h"
#include "CLodHandler.h"
#include "GameConstants.h"
@ -29,9 +30,17 @@ void trimQuotation(std::string &op)
op = op.substr(1,op.size()-2);
}
std::string getTextFile(std::string filename)
{
auto file = CResourceHandler::get()->loadData(
ResourceID(std::string("DATA/") + filename, EResType::TEXT));
return std::string((char*)file.first.get(), file.second);
}
void CGeneralTextHandler::load()
{
std::string buf1 = bitmaph->getTextFile("ZELP.TXT");
std::string buf1 = getTextFile("ZELP.TXT");
int itr=0, eol=-1, eolnext=-1, pom;
eolnext = buf1.find_first_of('\r',itr);
while(itr<buf1.size())
@ -55,7 +64,7 @@ void CGeneralTextHandler::load()
}
itr=eol+2;
}
std::string buf = bitmaph->getTextFile("VCDESC.TXT");
std::string buf = getTextFile("VCDESC.TXT");
int andame = buf.size();
int i=0; //buf iterator
for(int gg=0; gg<14; ++gg)
@ -69,7 +78,7 @@ void CGeneralTextHandler::load()
victoryConditions[gg] = buf.substr(befi, i-befi);
i+=2;
}
buf = bitmaph->getTextFile("LCDESC.TXT");
buf = getTextFile("LCDESC.TXT");
andame = buf.size();
i=0; //buf iterator
for(int gg=0; gg<4; ++gg)
@ -86,7 +95,7 @@ void CGeneralTextHandler::load()
hTxts.resize(GameConstants::HEROES_QUANTITY);
buf = bitmaph->getTextFile("HEROSPEC.TXT");
buf = getTextFile("HEROSPEC.TXT");
i=0;
std::string dump;
for(int iii=0; iii<2; ++iii)
@ -101,7 +110,7 @@ void CGeneralTextHandler::load()
trimQuotation(hTxts[iii].longBonus);
}
buf = bitmaph->getTextFile("HEROBIOS.TXT");
buf = getTextFile("HEROBIOS.TXT");
i=0;
for (int iii=0;iii<hTxts.size();iii++)
{
@ -110,7 +119,7 @@ void CGeneralTextHandler::load()
}
int it;
buf = bitmaph->getTextFile("BLDGNEUT.TXT");
buf = getTextFile("BLDGNEUT.TXT");
andame = buf.size(), it=0;
for(int b=0;b<15;b++)
@ -140,7 +149,7 @@ void CGeneralTextHandler::load()
}
/////done reading "BLDGNEUT.TXT"******************************
buf = bitmaph->getTextFile("BLDGSPEC.TXT");
buf = getTextFile("BLDGSPEC.TXT");
andame = buf.size(), it=0;
for(int f=0;f<GameConstants::F_NUMBER;f++)
{
@ -156,7 +165,7 @@ void CGeneralTextHandler::load()
}
/////done reading BLDGSPEC.TXT*********************************
buf = bitmaph->getTextFile("DWELLING.TXT");
buf = getTextFile("DWELLING.TXT");
andame = buf.size(), it=0;
for(int f=0;f<GameConstants::F_NUMBER;f++)
{
@ -178,7 +187,7 @@ void CGeneralTextHandler::load()
}
}
buf = bitmaph->getTextFile("TCOMMAND.TXT");
buf = getTextFile("TCOMMAND.TXT");
itr=0;
while(itr<buf.length()-1)
{
@ -187,7 +196,7 @@ void CGeneralTextHandler::load()
tcommands.push_back(tmp);
}
buf = bitmaph->getTextFile("HALLINFO.TXT");
buf = getTextFile("HALLINFO.TXT");
itr=0;
while(itr<buf.length()-1)
{
@ -196,7 +205,7 @@ void CGeneralTextHandler::load()
hcommands.push_back(tmp);
}
buf = bitmaph->getTextFile("CASTINFO.TXT");
buf = getTextFile("CASTINFO.TXT");
itr=0;
while(itr<buf.length()-1)
{
@ -206,8 +215,8 @@ void CGeneralTextHandler::load()
}
std::istringstream ins, namess;
ins.str(bitmaph->getTextFile("TOWNTYPE.TXT"));
namess.str(bitmaph->getTextFile("TOWNNAME.TXT"));
ins.str(getTextFile("TOWNTYPE.TXT"));
namess.str(getTextFile("TOWNNAME.TXT"));
int si=0;
char bufname[75];
while (!ins.eof())
@ -225,7 +234,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading OBJNAMES \n";
buf = bitmaph->getTextFile("OBJNAMES.TXT");
buf = getTextFile("OBJNAMES.TXT");
it=0; //hope that -1 will not break this
while (it<buf.length()-1)
{
@ -239,7 +248,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading ADVEVENT \n";
buf = bitmaph->getTextFile("ADVEVENT.TXT");
buf = getTextFile("ADVEVENT.TXT");
it=0;
std::string temp;
while (it<buf.length()-1)
@ -254,7 +263,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading XTRAINFO \n";
buf = bitmaph->getTextFile("XTRAINFO.TXT");
buf = getTextFile("XTRAINFO.TXT");
it=0;
while (it<buf.length()-1)
{
@ -263,7 +272,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading MINENAME \n";
buf = bitmaph->getTextFile("MINENAME.TXT");
buf = getTextFile("MINENAME.TXT");
it=0;
while (it<buf.length()-1)
{
@ -272,7 +281,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading MINEEVNT \n";
buf = bitmaph->getTextFile("MINEEVNT.TXT");
buf = getTextFile("MINEEVNT.TXT");
it=0;
i=0;
while (it<buf.length()-1)
@ -286,7 +295,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading RESTYPES \n";
buf = bitmaph->getTextFile("RESTYPES.TXT");
buf = getTextFile("RESTYPES.TXT");
it=0;
while (it<buf.length()-1)
{
@ -295,7 +304,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading TERRNAME \n";
buf = bitmaph->getTextFile("TERRNAME.TXT");
buf = getTextFile("TERRNAME.TXT");
it=0;
while (it<buf.length()-1)
{
@ -304,7 +313,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading RANDSIGN \n";
buf = bitmaph->getTextFile("RANDSIGN.TXT");
buf = getTextFile("RANDSIGN.TXT");
it=0;
while (it<buf.length()-1)
{
@ -313,7 +322,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading ZCRGN1 \n";
buf = bitmaph->getTextFile("ZCRGN1.TXT");
buf = getTextFile("ZCRGN1.TXT");
it=0;
while (it<buf.length()-1)
{
@ -322,7 +331,7 @@ void CGeneralTextHandler::load()
}
tlog5 << "\t\tReading CRGN4 \n";
buf = bitmaph->getTextFile("CRGEN4.TXT");
buf = getTextFile("CRGEN4.TXT");
it=0;
while (it<buf.length()-1)
{
@ -330,7 +339,7 @@ void CGeneralTextHandler::load()
creGens4.push_back(temp);
}
buf = bitmaph->getTextFile("GENRLTXT.TXT");
buf = getTextFile("GENRLTXT.TXT");
std::string tmp;
andame = buf.size();
i=0; //buf iterator
@ -350,7 +359,7 @@ void CGeneralTextHandler::load()
allTexts.push_back(buflet);
}
std::string stro = bitmaph->getTextFile("Overview.txt");
std::string stro = getTextFile("Overview.txt");
itr=0;
while(itr<stro.length()-1)
{
@ -359,7 +368,7 @@ void CGeneralTextHandler::load()
overview.push_back(tmp);
}
std::string strc = bitmaph->getTextFile("PLCOLORS.TXT");
std::string strc = getTextFile("PLCOLORS.TXT");
itr=0;
while(itr<strc.length()-1)
{
@ -369,7 +378,7 @@ void CGeneralTextHandler::load()
capColors.push_back(tmp);
}
std::string strs = bitmaph->getTextFile("ARRAYTXT.TXT");
std::string strs = getTextFile("ARRAYTXT.TXT");
itr=0;
while(itr<strs.length()-1)
@ -380,7 +389,7 @@ void CGeneralTextHandler::load()
}
itr = 0;
std::string strin = bitmaph->getTextFile("PRISKILL.TXT");
std::string strin = getTextFile("PRISKILL.TXT");
for(int hh=0; hh<4; ++hh)
{
loadToIt(tmp, strin, itr, 3);
@ -388,7 +397,7 @@ void CGeneralTextHandler::load()
}
itr = 0;
strin = bitmaph->getTextFile("JKTEXT.TXT");
strin = getTextFile("JKTEXT.TXT");
for(int hh=0; hh<45; ++hh)
{
loadToIt(tmp, strin, itr, 3);
@ -397,7 +406,7 @@ void CGeneralTextHandler::load()
}
itr = 0;
strin = bitmaph->getTextFile("TVRNINFO.TXT");
strin = getTextFile("TVRNINFO.TXT");
for(int hh=0; hh<8; ++hh)
{
loadToIt(tmp, strin, itr, 3);
@ -405,7 +414,7 @@ void CGeneralTextHandler::load()
}
itr = 0;
strin = bitmaph->getTextFile("TURNDUR.TXT");
strin = getTextFile("TURNDUR.TXT");
for(int hh=0; hh<11; ++hh)
{
loadToIt(tmp, strin, itr, 3);
@ -413,7 +422,7 @@ void CGeneralTextHandler::load()
}
itr = 0;
strin = bitmaph->getTextFile("HEROSCRN.TXT");
strin = getTextFile("HEROSCRN.TXT");
for(int hh=0; hh<33; ++hh)
{
loadToIt(tmp, strin, itr, 3);
@ -421,7 +430,7 @@ void CGeneralTextHandler::load()
}
itr = 0;
strin = bitmaph->getTextFile("ARTEVENT.TXT");
strin = getTextFile("ARTEVENT.TXT");
for(; itr<strin.size();)
{
loadToIt(tmp, strin, itr, 2);
@ -431,7 +440,7 @@ void CGeneralTextHandler::load()
artifEvents.push_back(tmp);
}
buf = bitmaph->getTextFile("SSTRAITS.TXT");
buf = getTextFile("SSTRAITS.TXT");
it=0;
for(int i=0; i<2; ++i)
@ -449,7 +458,7 @@ void CGeneralTextHandler::load()
for(int j = 0; j < 3; j++)
trimQuotation(skillInfoTexts[i][j]);
}
buf = bitmaph->getTextFile("SKILLLEV.TXT");
buf = getTextFile("SKILLLEV.TXT");
it=0;
for(int i=0; i<6; ++i)
{
@ -458,7 +467,7 @@ void CGeneralTextHandler::load()
levels.push_back(buffo);
}
buf = bitmaph->getTextFile ("SEERHUT.TXT");
buf = getTextFile ("SEERHUT.TXT");
it = 0;
loadToIt (dump, buf, it, 3);
loadToIt (dump, buf, it, 4); //dump description
@ -502,7 +511,7 @@ void CGeneralTextHandler::load()
for (i = 0; i < 48; ++i)
loadToIt(seerNames[i], buf, it, 3);
buf = bitmaph->getTextFile("TENTCOLR.TXT");
buf = getTextFile("TENTCOLR.TXT");
itr=0;
while(itr<buf.length()-1)
{
@ -512,7 +521,7 @@ void CGeneralTextHandler::load()
}
//campaigns
buf = bitmaph->getTextFile ("CAMPTEXT.TXT");
buf = getTextFile ("CAMPTEXT.TXT");
it = 0;
loadToIt (dump, buf, it, 3); //comment
std::string nameBuf;
@ -542,7 +551,7 @@ void CGeneralTextHandler::load()
} while (nameBuf.size());
}
buf = bitmaph->getTextFile ("ZCREXP.TXT");
buf = getTextFile ("ZCREXP.TXT");
it = 0;
loadToIt (dump, buf, it, 3); //comment
for (int i = 0; i < 459; ++i) //some texts seem to be empty

View File

@ -1,6 +1,7 @@
#include "StdInc.h"
#include "CHeroHandler.h"
#include "Filesystem/CResourceLoader.h"
#include "CLodHandler.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/JsonNode.h"
@ -8,7 +9,6 @@
#include <boost/version.hpp>
#include "BattleHex.h"
extern CLodHandler * bitmaph;
void loadToIt(std::string &dest, const std::string &src, int &iter, int mode);
/*
* CHeroHandler.cpp, part of VCMI engine
@ -165,7 +165,8 @@ void CHeroHandler::loadPuzzleInfo()
void CHeroHandler::loadHeroes()
{
VLC->heroh = this;
std::string buf = bitmaph->getTextFile("HOTRAITS.TXT");
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/HOTRAITS.TXT"));
std::string buf((char*)textFile.first.get(), textFile.second);
int it=0;
std::string dump;
for(int i=0; i<2; ++i)
@ -286,7 +287,8 @@ void CHeroHandler::loadHeroes()
expPerLevel.pop_back();//last value is broken
//ballistics info
buf = bitmaph->getTextFile("BALLIST.TXT");
textFile = CResourceHandler::get()->loadData(ResourceID("DATA/BALLIST.TXT"));
buf = std::string((char*)textFile.first.get(), textFile.second);
it = 0;
for(int i=0; i<22; ++i)
{
@ -324,7 +326,8 @@ void CHeroHandler::loadHeroes()
void CHeroHandler::loadHeroClasses()
{
std::istringstream str(bitmaph->getTextFile("HCTRAITS.TXT")); //we'll be reading from it
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/HCTRAITS.TXT"));
std::istringstream str(std::string((char*)textFile.first.get(), textFile.second)); //we'll be reading from it
const int BUFFER_SIZE = 5000;
char buffer[BUFFER_SIZE+1];

View File

@ -1,15 +1,11 @@
#include "StdInc.h"
#include "CLodHandler.h"
#include "zlib.h"
#include "vcmi_endian.h"
#include "VCMIDirs.h"
#ifdef max
#undef max
#endif
extern VCMIDirs GVCMIDirs;
/*
* CLodHandler.cpp, part of VCMI engine
*
@ -21,7 +17,7 @@ extern VCMIDirs GVCMIDirs;
*/
std::string readString(const ui8 * bufor, int &i)
{
{
int len = read_le_u32(bufor + i); i+=4;
assert(len >= 0 && len <= 500000); //not too long
std::string ret; ret.reserve(len);
@ -31,7 +27,7 @@ std::string readString(const ui8 * bufor, int &i)
}
return ret;
}
/*
void CLodHandler::convertName(std::string &filename, std::string *extension)
{
std::transform(filename.begin(), filename.end(), filename.begin(), toupper);
@ -132,7 +128,7 @@ DLL_LINKAGE int CLodHandler::infs2(ui8 * in, int size, int realSize, ui8 *& out,
out = new ui8 [realSize];
int latPosOut = 0;
/* allocate inflate state */
// allocate inflate state
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
@ -151,13 +147,13 @@ DLL_LINKAGE int CLodHandler::infs2(ui8 * in, int size, int realSize, ui8 *& out,
break;
strm.next_in = in + chunkNumber * NLoadHandlerHelp::fCHUNK;
/* run inflate() on input until output buffer not full */
// run inflate() on input until output buffer not full
do
{
strm.avail_out = realSize - latPosOut;
strm.next_out = out + latPosOut;
ret = inflate(&strm, Z_NO_FLUSH);
//assert(ret != Z_STREAM_ERROR); /* state not clobbered */
//assert(ret != Z_STREAM_ERROR); // state not clobbered
bool breakLoop = false;
switch (ret)
{
@ -165,7 +161,7 @@ DLL_LINKAGE int CLodHandler::infs2(ui8 * in, int size, int realSize, ui8 *& out,
breakLoop = true;
break;
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
ret = Z_DATA_ERROR; // and fall through
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
@ -180,10 +176,10 @@ DLL_LINKAGE int CLodHandler::infs2(ui8 * in, int size, int realSize, ui8 *& out,
} while (strm.avail_out == 0);
++chunkNumber;
/* done when inflate() says it's done */
// done when inflate() says it's done
} while (ret != Z_STREAM_END);
/* clean up and return */
// clean up and return
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
@ -399,3 +395,4 @@ ui8 * CLodHandler::getUnpackedFile( const std::string & path, int * sizeOut )
*sizeOut = mapsize;
return initTable;
}
*/

View File

@ -12,22 +12,23 @@
*
*/
namespace boost
{class mutex;}
namespace NLoadHandlerHelp
{
const int dmHelp=0, dmNoExtractingMask=1;
//std::string P1,P2,CurDir;
const int fCHUNK = 50000;
}
struct LodEntry {
char filename[16];
ui32 offset; /* little endian */
ui32 uncompressedSize; /* little endian */
ui32 unused; /* little endian */
ui32 size; /* little endian */
};
//namespace boost
//{class mutex;}
//namespace NLoadHandlerHelp
//{
// const int dmHelp=0, dmNoExtractingMask=1;
// //std::string P1,P2,CurDir;
// const int fCHUNK = 50000;
//}
//struct LodEntry {
// char filename[16];
// ui32 offset; /* little endian */
// ui32 uncompressedSize; /* little endian */
// ui32 unused; /* little endian */
// ui32 size; /* little endian */
//};
static inline char readChar(const ui8 * bufor, int &i)
{
@ -35,7 +36,7 @@ static inline char readChar(const ui8 * bufor, int &i)
}
DLL_LINKAGE std::string readString(const ui8 * bufor, int &i);
/*
enum LodFileType{
FILE_ANY,
FILE_TEXT,
@ -97,23 +98,20 @@ class DLL_LINKAGE CLodHandler
void initEntry(Entry &e, const std::string name);
int infs2(ui8 * in, int size, int realSize, ui8*& out, int wBits=15); //zlib fast handler
public:
//convert string to upper case and remove extension. If extension!=NULL -> it will be copied here (including dot)
void convertName(std::string &filename, std::string *extension=NULL);
ui8 * giveFile(std::string defName, LodFileType type=FILE_ANY, int * length=NULL);
boost::unordered_set<Entry> entries;
void extractFile(const std::string FName, const std::string name, LodFileType type=FILE_ANY);
static ui8 * getUnpackedData(ui8 *data, size_t inputSize, int * outputSize);
void convertName(std::string &filename, std::string *extension=NULL);
std::string getFileName(std::string lodFile, LodFileType type=FILE_ANY);
bool haveFile(std::string name, LodFileType type=FILE_ANY);
static ui8 * getUnpackedFile(const std::string & path, int * sizeOut);
std::string getTextFile(std::string name, LodFileType type=FILE_TEXT); //extracts one file
CLodHandler();
~CLodHandler();
void init(const std::string lodFile, const std::string dirName);
std::string getFileName(std::string lodFile, LodFileType type=FILE_ANY);
ui8 * giveFile(std::string defName, LodFileType type=FILE_ANY, int * length=NULL); //returns pointer to the decompressed data - it must be deleted when no longer needed!
bool haveFile(std::string name, LodFileType type=FILE_ANY);//check if file is present in lod
std::string getTextFile(std::string name, LodFileType type=FILE_TEXT); //extracts one file
void extractFile(const std::string FName, const std::string name, LodFileType type=FILE_ANY); //extracts a specific file
//unpack data from memory, input data will be deleted
static ui8 * getUnpackedData(ui8 *data, size_t inputSize, int * outputSize);
//loads given file, decompresses and returns
static ui8 * getUnpackedFile(const std::string & path, int * sizeOut);
};
*/

View File

@ -12,7 +12,7 @@ set(lib_SRCS
Filesystem/CLodArchiveLoader.cpp
Filesystem/CResourceLoader.cpp
Filesystem/CFileInputStream.cpp
Filesystem/CLodStream.cpp
Filesystem/CCompressedStream.cpp
Filesystem/ISimpleResourceLoader.cpp
BattleAction.cpp
BattleHex.cpp

View File

@ -8,13 +8,13 @@
void CMapInfo::countPlayers()
{
actualHumanPlayers = playerAmnt = humenPlayers = 0;
actualHumanPlayers = playerAmnt = humanPlayers = 0;
for(int i=0;i<GameConstants::PLAYER_LIMIT;i++)
{
if(mapHeader->players[i].canHumanPlay)
{
playerAmnt++;
humenPlayers++;
humanPlayers++;
}
else if(mapHeader->players[i].canComputerPlay)
{
@ -35,7 +35,7 @@ CMapInfo::CMapInfo(bool map)
void CMapInfo::mapInit(const std::string &fname, const ui8 *map )
{
filename = fname;
fileURI = fname;
int i = 0;
mapHeader = new CMapHeader();
mapHeader->version = CMapHeader::invalid;
@ -61,7 +61,7 @@ CMapInfo::~CMapInfo()
void CMapInfo::campaignInit()
{
campaignHeader = new CCampaignHeader( CCampaignHandler::getHeader(filename, lodCmpgn) );
campaignHeader = new CCampaignHeader( CCampaignHandler::getHeader(fileURI) );
}
void CMapInfo::setHeader(CMapHeader *header)

View File

@ -14,11 +14,10 @@ public:
CMapHeader * mapHeader; //may be NULL if campaign
CCampaignHeader * campaignHeader; //may be NULL if scenario
StartInfo *scenarioOpts; //options with which scenario has been started (used only with saved games)
std::string filename;
bool lodCmpgn; //tells if this campaign is located in Lod file
std::string fileURI;
std::string date;
int playerAmnt, //players in map
humenPlayers; //players ALLOWED to be controlled by human
humanPlayers; //players ALLOWED to be controlled by human
int actualHumanPlayers; // >1 if multiplayer game
CMapInfo(bool map = true);
~CMapInfo();
@ -30,7 +29,7 @@ public:
template <typename Handler> void serialize(Handler &h, const int Version)
{
h & mapHeader & campaignHeader & scenarioOpts & filename & lodCmpgn & date & playerAmnt & humenPlayers;
h & mapHeader & campaignHeader & scenarioOpts & fileURI & date & playerAmnt & humanPlayers;
h & actualHumanPlayers;
}
};

View File

@ -43,7 +43,6 @@ std::map<int,std::map<int, std::vector<int> > > CGTeleport::objs;
std::vector<std::pair<int, int> > CGTeleport::gates;
IGameCallback * IObjectInterface::cb = NULL;
DLL_LINKAGE void loadToIt(std::string &dest, const std::string &src, int &iter, int mode);
extern CLodHandler * bitmaph;
extern boost::rand48 ran;
std::map <ui8, std::set <ui8> > CGKeys::playerKeyMap;
std::map <si32, std::vector<si32> > CGMagi::eyelist;

View File

@ -1,7 +1,7 @@
#include "StdInc.h"
#include "CSpellHandler.h"
#include "Filesystem/CResourceLoader.h"
#include "CLodHandler.h"
#include "../lib/VCMI_Lib.h"
#include "../lib/JsonNode.h"
@ -9,8 +9,6 @@
#include "GameConstants.h"
#include "BattleHex.h"
extern CLodHandler *bitmaph;
/*
* CSpellHandler.cpp, part of VCMI engine
*
@ -274,7 +272,10 @@ bool DLL_LINKAGE isInScreenRange(const int3 &center, const int3 &pos)
void CSpellHandler::loadSpells()
{
std::string buf = bitmaph->getTextFile("SPTRAITS.TXT"), pom;
auto textFile = CResourceHandler::get()->loadData(ResourceID("DATA/SPTRAITS.TXT"));
std::string buf((char*)textFile.first.get(), textFile.second);
std::string pom;
int andame = buf.size(), i=0; //buf iterator
for(int z=0; z<5; ++z)
loadToIt(pom,buf,i,3);

View File

@ -0,0 +1,162 @@
#include "StdInc.h"
#include "CCompressedStream.h"
#include <zlib.h>
static const int inflateBlockSize = 10000;
CCompressedStream::CCompressedStream(std::unique_ptr<CInputStream> & stream, bool gzip, size_t decompressedSize):
gzipStream(std::move(stream)),
buffer(decompressedSize),
decompressedSize(0),
compressedBuffer(inflateBlockSize),
position(0)
{
assert(gzipStream);
// Allocate inflate state
inflateState = new z_stream;
inflateState->zalloc = Z_NULL;
inflateState->zfree = Z_NULL;
inflateState->opaque = Z_NULL;
inflateState->avail_in = 0;
inflateState->next_in = Z_NULL;
int wbits = 15;
if (gzip)
wbits += 16;
int ret = inflateInit2(inflateState, wbits);
if (ret != Z_OK)
throw std::runtime_error("Failed to initialize inflate!\n");
}
CCompressedStream::~CCompressedStream()
{
delete inflateState;
}
si64 CCompressedStream::read(ui8 * data, si64 size)
{
decompressTill(position + size);
auto start = buffer.begin() + position;
si64 toRead = std::min<si64>(size, decompressedSize - position);
std::copy(start, start + toRead, data);
position += toRead;
return size;
}
si64 CCompressedStream::seek(si64 position)
{
decompressTill(position);
this->position = std::min<si64>(position, decompressedSize);
return this->position;
}
si64 CCompressedStream::tell()
{
return position;
}
si64 CCompressedStream::skip(si64 delta)
{
decompressTill(position + delta);
si64 oldPosition = position;
position = std::min<si64>(position + delta , decompressedSize);
return position - oldPosition;
}
si64 CCompressedStream::getSize()
{
decompressTill(-1);
return decompressedSize;
}
void CCompressedStream::decompressTill(si64 newSize)
{
//TODO: check if inflate have any special mode for inflating (e.g Z_BLOCK) that can
// be used for campaigns Technically .h3c consists from multiple
// concatenated gz streams (campaign header + every map)
// inflatings them separately can be useful for campaigns loading
assert(newSize < 100 * 1024 * 1024); //just in case
if (inflateState == nullptr)
return; //file already decompressed
if (newSize >= 0 && newSize < inflateState->total_out)
return; //no need to decompress anything
bool toEnd = newSize < 0;
if (toEnd && buffer.empty())
buffer.resize(16 * 1024); //some space for initial decompression
if (!toEnd && buffer.size() < newSize)
buffer.resize(newSize);
int ret;
int endLoop = false;
do
{
if (inflateState->avail_in == 0)
{
//inflate ran out of available data or was not initialized yet
// get new input data and update state accordingly
si64 size = gzipStream->read(compressedBuffer.data(), compressedBuffer.size());
if (size != compressedBuffer.size())
toEnd = true; //end of file reached
inflateState->avail_in = size;
inflateState->next_in = compressedBuffer.data();
}
inflateState->avail_out = buffer.size() - inflateState->total_out;
inflateState->next_out = buffer.data() + inflateState->total_out;
ret = inflate(inflateState, Z_NO_FLUSH);
switch (ret)
{
case Z_STREAM_END: //end decompression
endLoop = true;
break;
case Z_OK: //decompress next chunk
endLoop = false;
break;
case Z_BUF_ERROR:
{
if (toEnd)
{
//not enough memory. Allocate bigger buffer and try again
buffer.resize(buffer.size() * 2);
endLoop = false;
}
else
{
assert(inflateState->total_out == newSize);
endLoop = true;
}
}
break;
default:
throw std::runtime_error("Decompression error!\n");
}
}
while (!endLoop);
// Clean up and return
if (toEnd)
{
inflateEnd(inflateState);
buffer.resize(inflateState->total_out);
decompressedSize = inflateState->total_out;
vstd::clear_pointer(inflateState);
}
else
decompressedSize = inflateState->total_out;
}

View File

@ -0,0 +1,102 @@
/*
* CLodStream.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "CInputStream.h"
struct z_stream_s;
/**
* A class which provides method definitions for reading a gzip-compressed file
* This class implements lazy loading - data will be decompressed (and cached by this class) only by request
*/
class DLL_LINKAGE CCompressedStream : public CInputStream
{
public:
/**
* C-tor.
*
* @param stream - stream with compresed data
* @param gzip - this is gzipp'ed file e.g. campaign or maps, false for files in lod
* @param decompressedSize - optional parameter to hint size of decompressed data
*/
CCompressedStream(std::unique_ptr<CInputStream> & stream, bool gzip, size_t decompressedSize=0);
~CCompressedStream();
/**
* Reads n bytes from the stream into the data buffer.
*
* @param data A pointer to the destination data array.
* @param size The number of bytes to read.
* @return the number of bytes read actually.
*
* @throws std::runtime_error if the file decompression was not successful
*/
si64 read(ui8 * data, si64 size);
/**
* Seeks the internal read pointer to the specified position.
* This will cause decompressing data till this position is found
*
* @param position The read position from the beginning.
* @return the position actually moved to, -1 on error.
*/
si64 seek(si64 position);
/**
* Gets the current read position in the stream.
*
* @return the read position.
*/
si64 tell();
/**
* Skips delta numbers of bytes.
*
* @param delta The count of bytes to skip.
* @return the count of bytes skipped actually.
*/
si64 skip(si64 delta);
/**
* Gets the length in bytes of the stream.
* Causes complete data decompression
*
* @return the length in bytes of the stream.
*/
si64 getSize();
private:
/**
* Decompresses data to ensure that buffer has newSize bytes or end of stream was reached
*/
void decompressTill(si64 newSize);
/** The file stream with compressed data. */
std::unique_ptr<CInputStream> gzipStream;
/** buffer with already decompressed data. Please note that size() != decompressed size */
std::vector<ui8> buffer;
/** size of already decompressed data */
si64 decompressedSize;
/** buffer with not yet decompressed data*/
std::vector<ui8> compressedBuffer;
/** struct with current zlib inflate state */
z_stream_s * inflateState;
/** Current read position */
si64 position;
};

View File

@ -65,12 +65,25 @@ std::string CFileInfo::getStem() const
if(dotPos != std::string::npos && name[dotPos] == '.')
rslt.erase(dotPos);
// Remove path
size_t found = rslt.find_last_of("/\\");
return rslt.substr(found + 1);
return rslt;
}
EResType CFileInfo::getType() const
std::string CFileInfo::getBaseName() const
{
size_t end = name.find_last_of("/.");
size_t begin = name.find_last_of("/");
if(end != std::string::npos && name[end] == '.')
end = std::string::npos;
if(begin == std::string::npos)
begin = 0;
return name.substr(begin, end);
}
EResType::Type CFileInfo::getType() const
{
return EResTypeHelper::getTypeFromExtension(getExtension());
}
@ -88,20 +101,30 @@ std::unique_ptr<std::list<CFileInfo> > CFileInfo::listFiles(size_t depth, const
{
std::list<CFileInfo> * fileList = new std::list<CFileInfo>;
std::vector<std::string> path;
boost::filesystem::recursive_directory_iterator enddir;
for(boost::filesystem::recursive_directory_iterator it(name); it != enddir; ++it)
boost::filesystem::recursive_directory_iterator it(name, boost::filesystem::symlink_option::recurse);
for(; it != enddir; ++it)
{
if (boost::filesystem::is_directory(it->status()))
{
it.no_push(depth >= it.level());
path.resize(it.level()+1);
path.back() = it->path().leaf().string();
it.no_push(depth <= it.level());
}
if(boost::filesystem::is_regular(it->status()))
if(extensionFilter.empty() || it->path().extension() == extensionFilter)
{
if(extensionFilter == "" || it->path().extension() == extensionFilter)
{
CFileInfo file(it->path().string());
fileList->push_back(file);
}
std::string filename;
for (size_t i=0; i<it.level() && i<path.size(); i++)
filename += path[i] + '/';
filename += it->path().leaf().string();
//tlog1 << "Found file: " << filename << "\n";
CFileInfo file(filename);
fileList->push_back(file);
}
}

View File

@ -81,18 +81,25 @@ public:
std::string getFilename() const;
/**
* Gets the file name exclusive the extension of the file.
* Gets the file name + path exclusive the extension of the file.
*
* @return the file name exclusive the extension of the file. E.g. foo
* @return the file name exclusive the extension of the file. E.g. ./dir/foo
*/
std::string getStem() const;
/**
* Gets the file name exclusive the extension of the file.
*
* @return the file name exclusive the extension and a path of the file. E.g. foo
*/
std::string getBaseName() const;
/**
* Gets the extension type as a EResType enumeration.
*
* @return the extension type as a EResType enumeration.
*/
EResType getType() const;
EResType::Type getType() const;
/**
* Gets the timestamp of the file.

View File

@ -7,14 +7,14 @@ CFileInputStream::CFileInputStream()
}
CFileInputStream::CFileInputStream(const std::string & file)
CFileInputStream::CFileInputStream(const std::string & file, si64 start, si64 size)
{
open(file);
open(file, start, size);
}
CFileInputStream::CFileInputStream(const CFileInfo & file)
CFileInputStream::CFileInputStream(const CFileInfo & file, si64 start, si64 size)
{
open(file);
open(file.getName(), start, size);
}
CFileInputStream::~CFileInputStream()
@ -22,53 +22,62 @@ CFileInputStream::~CFileInputStream()
close();
}
void CFileInputStream::open(const std::string & file)
void CFileInputStream::open(const std::string & file, si64 start, si64 size)
{
close();
fileStream.open(file.c_str(), std::ios::in | std::ios::binary);
if (fileStream.fail())
{
throw std::runtime_error("File " + file + " isn't available.");
}
}
void CFileInputStream::open(const CFileInfo & file)
{
open(file.getName());
dataStart = start;
dataSize = size;
if (dataSize == 0)
{
fileStream.seekg(0, std::ios::end);
dataSize = tell();
}
fileStream.seekg(start, std::ios::beg);
}
si64 CFileInputStream::read(ui8 * data, si64 size)
{
fileStream.read(reinterpret_cast<char *>(data), size);
si64 origin = tell();
si64 toRead = std::min(dataSize - origin, size);
fileStream.read(reinterpret_cast<char *>(data), toRead);
return fileStream.gcount();
}
si64 CFileInputStream::seek(si64 position)
{
si64 diff = tell();
fileStream.seekg(position);
fileStream.seekg(dataStart + std::min(position, dataSize));
return tell() - diff;
return tell();
}
si64 CFileInputStream::tell()
{
return fileStream.tellg();
return fileStream.tellg() - dataStart;
}
si64 CFileInputStream::skip(si64 delta)
{
si64 diff = tell();
fileStream.seekg(delta, std::ios::cur);
si64 origin = tell();
//ensure that we're not seeking past the end of real data
si64 toSeek = std::min(dataSize - origin, delta);
fileStream.seekg(toSeek, std::ios::cur);
return tell() - diff;
return tell() - origin;
}
si64 CFileInputStream::getSize()
{
fileStream.seekg(0, std::ios::end);
return fileStream.tellg();
return dataSize;
}
void CFileInputStream::close()

View File

@ -29,20 +29,16 @@ public:
/**
* C-tor. Opens the specified file.
*
* @param file Path to the file.
*
* @throws std::runtime_error if file wasn't found
* @see CFileInputStream::open
*/
CFileInputStream(const std::string & file);
CFileInputStream(const std::string & file, si64 start=0, si64 size=0);
/**
* C-tor. Opens the specified file.
*
* @param file A file info object, pointing to a location in the file system
*
* @throws std::runtime_error if file wasn't found
* @see CFileInputStream::open
*/
CFileInputStream(const CFileInfo & file);
CFileInputStream(const CFileInfo & file, si64 start=0, si64 size=0);
/**
* D-tor. Calls the close method implicitely, if the file is still opened.
@ -53,19 +49,12 @@ public:
* Opens a file. If a file is currently opened, it will be closed.
*
* @param file Path to the file.
* @param start - offset from file start where real data starts (e.g file on archive)
* @param size - size of real data in file (e.g file on archive) or 0 to use whole file
*
* @throws std::runtime_error if file wasn't found
*/
void open(const std::string & file);
/**
* Opens a file.
*
* @param file A file info object, pointing to a location in the file system
*
* @throws std::runtime_error if file wasn't found
*/
void open(const CFileInfo & file);
void open(const std::string & file, si64 start, si64 size);
/**
* Reads n bytes from the stream into the data buffer.
@ -112,6 +101,8 @@ public:
void close();
private:
si64 dataStart;
si64 dataSize;
/** Native c++ input file stream object. */
std::ifstream fileStream;
};

View File

@ -16,7 +16,7 @@ CFilesystemLoader::CFilesystemLoader(const std::string & baseDirectory, size_t d
CFilesystemLoader::CFilesystemLoader(const CFileInfo & baseDirectory, size_t depth)
{
open(baseDirectory, depth);
open(baseDirectory.getName(), depth);
}
void CFilesystemLoader::open(const std::string & baseDirectory, size_t depth)
@ -27,20 +27,13 @@ void CFilesystemLoader::open(const std::string & baseDirectory, size_t depth)
std::unique_ptr<std::list<CFileInfo> > fileList = directory.listFiles(depth);
if(fileList)
{
throw std::runtime_error("Directory " + baseDirectory + " not available.");
this->fileList = std::move(*fileList);
}
this->fileList = std::move(*fileList);
}
void CFilesystemLoader::open(const CFileInfo & baseDirectory, size_t depth)
{
open(baseDirectory.getName(), depth);
}
std::unique_ptr<CInputStream> CFilesystemLoader::load(const std::string & resourceName) const
{
std::unique_ptr<CInputStream> stream(new CFileInputStream(resourceName));
std::unique_ptr<CInputStream> stream(new CFileInputStream(getOrigin() + '/' + resourceName));
return stream;
}
@ -48,7 +41,7 @@ bool CFilesystemLoader::existsEntry(const std::string & resourceName) const
{
for(auto it = fileList.begin(); it != fileList.end(); ++it)
{
if((*it).getName() == resourceName)
if(it->getName() == resourceName)
{
return true;
}
@ -68,3 +61,8 @@ std::list<std::string> CFilesystemLoader::getEntries() const
return std::move(retList);
}
std::string CFilesystemLoader::getOrigin() const
{
return baseDirectory;
}

View File

@ -55,15 +55,6 @@ public:
*/
void open(const std::string & baseDirectory, size_t depth);
/**
* Opens a base directory to be read and indexed.
*
* @param baseDirectory Specifies the base directory and their sub-directories which should be indexed.
*
* @throws std::runtime_error if the base directory is not a directory or if it is not available
*/
void open(const CFileInfo & baseDirectory, size_t depth);
/**
* Loads a resource with the given resource name.
*
@ -86,6 +77,13 @@ public:
*/
std::list<std::string> getEntries() const;
/**
* Gets the origin of the archive loader.
*
* @return the file path to directory with archive (e.g. path/to/h3/mp3)
*/
std::string getOrigin() const;
private:
/** The base directory which is scanned and indexed. */
std::string baseDirectory;

View File

@ -64,5 +64,5 @@ public:
/**
* Closes the stream and releases any system resources associated with the stream explicitely.
*/
virtual void close() = 0;
//virtual void close() = 0;
};

View File

@ -2,6 +2,7 @@
#include "CLodArchiveLoader.h"
#include "CInputStream.h"
#include "CFileInputStream.h"
#include "CCompressedStream.h"
#include "CLodStream.h"
#include "CBinaryReader.h"
#include "CFileInfo.h"
@ -40,7 +41,7 @@ void CLodArchiveLoader::open(const std::string & archive)
boost::to_upper(ext);
// Init the specific lod container format
if(ext == ".LOD")
if(ext == ".LOD" || ext == ".PAC")
{
initLODArchive(fileStream);
}
@ -170,7 +171,7 @@ void CLodArchiveLoader::initSNDArchive(CFileInputStream & fileStream)
fileStream.read(reinterpret_cast<ui8 *>(sndEntries), sizeof(struct SoundEntryBlock) * totalFiles);
// Insert entries to list
for(ui8 i = 0; i < totalFiles; i++)
for(ui32 i = 0; i < totalFiles; i++)
{
SoundEntryBlock sndEntry = sndEntries[i];
ArchiveEntry entry;
@ -188,8 +189,20 @@ void CLodArchiveLoader::initSNDArchive(CFileInputStream & fileStream)
std::unique_ptr<CInputStream> CLodArchiveLoader::load(const std::string & resourceName) const
{
std::unique_ptr<CInputStream> stream(new CLodStream(this, resourceName));
return stream;
assert(existsEntry(resourceName));
const ArchiveEntry & entry = entries.find(resourceName)->second;
if (entry.size != 0) //compressed data
{
std::unique_ptr<CInputStream> fileStream(new CFileInputStream(getOrigin(), entry.offset, entry.size));
return std::unique_ptr<CInputStream>(new CCompressedStream(fileStream, false, entry.realSize));
}
else
{
return std::unique_ptr<CInputStream>(new CFileInputStream(getOrigin(), entry.offset, entry.realSize));
}
}
std::list<std::string> CLodArchiveLoader::getEntries() const
@ -219,15 +232,7 @@ const ArchiveEntry * CLodArchiveLoader::getArchiveEntry(const std::string & reso
bool CLodArchiveLoader::existsEntry(const std::string & resourceName) const
{
auto it = entries.find(resourceName);
if(it != entries.end())
{
return true;
}
else
{
return false;
}
return entries.find(resourceName) != entries.end();
}
std::string CLodArchiveLoader::getOrigin() const

View File

@ -35,7 +35,7 @@ struct ArchiveEntry
/** Size without compression in bytes **/
int realSize;
/** Size within compression in bytes **/
/** Size with compression in bytes or 0 if not compressed **/
int size;
};

View File

@ -1,8 +1,9 @@
#include "StdInc.h"
#include "CLodStream.h"
/*
#include "CLodArchiveLoader.h"
#include "CFileInputStream.h"
#include "CMemoryStream.h"
CLodStream::CLodStream()
{
@ -16,74 +17,60 @@ CLodStream::CLodStream(const CLodArchiveLoader * loader, const std::string & res
void CLodStream::open(const CLodArchiveLoader * loader, const std::string & resourceName)
{
close();
assert(!fileStream);
const ArchiveEntry * archiveEntry = loader->getArchiveEntry(resourceName);
if(archiveEntry == nullptr)
{
throw std::runtime_error("Archive entry " + resourceName + " wasn't found in the archive " + loader->getOrigin());
}
this->archiveEntry = archiveEntry;
size = archiveEntry->size;
offset = archiveEntry->offset;
// Open the archive and set the read pointer to the correct position
fileStream.open(loader->getOrigin());
fileStream.seek(this->archiveEntry->offset);
fileStream.reset(new CFileInputStream(loader->getOrigin()));
fileStream->seek(archiveEntry->offset);
// Decompress file
if(archiveEntry->size != 0)
{
// replace original buffer with decompressed one
fileStream.reset(CLodArchiveLoader::decompress(*this, archiveEntry->realSize));
assert(fileStream->getSize() == archiveEntry->realSize);
//in memory stream we no longer need offset
offset = 0;
}
size = archiveEntry->realSize;
}
si64 CLodStream::read(ui8 * data, si64 size)
{
// Test whether the file has to be decompressed
if(archiveEntry->size == 0)
{
// No decompression
return fileStream.read(data, size);
}
else
{
// Decompress file
// We can't decompress partially, so the size of the output buffer has to be minimum the
// size of the decompressed lod entry. If this isn't the case, it is a programming fault.
assert(size >= archiveEntry->realSize);
// Read the compressed data into a buffer
auto comp = std::unique_ptr<ui8[]>(new ui8[archiveEntry->size]);
fileStream.read(comp.get(), archiveEntry->size);
// Decompress the file
data = CLodArchiveLoader::decompressFile(comp.get(), archiveEntry->size, archiveEntry->realSize).first;
if (!data)
{
throw std::runtime_error("File decompression wasn't successful. Resource name: " + archiveEntry->name);
}
// We're reading the total size always
return archiveEntry->realSize;
}
return fileStream->read(data, size);
}
si64 CLodStream::seek(si64 position)
{
return fileStream.seek(archiveEntry->offset + position);
return fileStream->seek(offset + position);
}
si64 CLodStream::tell()
{
return fileStream.tell() - archiveEntry->offset;
return fileStream->tell() - offset;
}
si64 CLodStream::skip(si64 delta)
{
return fileStream.skip(delta);
return fileStream->skip(delta);
}
si64 CLodStream::getSize()
{
return archiveEntry->realSize;
return size;
}
void CLodStream::close()
{
fileStream.close();
fileStream->close();
}
*/

View File

@ -11,95 +11,98 @@
#pragma once
#include "CInputStream.h"
#include "CFileInputStream.h"
#include "CLodArchiveLoader.h"
//#include "CInputStream.h"
//#include "CFileInputStream.h"
//#include "CLodArchiveLoader.h"
/**
* A class which provides method definitions for reading a file from a LOD archive.
*/
class DLL_LINKAGE CLodStream : public CInputStream
{
public:
/**
* Default c-tor.
*/
CLodStream();
///**
// * A class which provides method definitions for reading a file from a LOD archive.
// */
//class DLL_LINKAGE CLodStream : public CInputStream
//{
//public:
// /**
// * Default c-tor.
// */
// CLodStream();
/**
* C-tor.
*
* @param loader The archive loader object which knows about the structure of the archive format.
* @param resourceName The resource name which says what resource should be loaded.
*
* @throws std::runtime_error if the archive entry wasn't found
*/
CLodStream(const CLodArchiveLoader * loader, const std::string & resourceName);
// /**
// * C-tor.
// *
// * @param loader The archive loader object which knows about the structure of the archive format.
// * @param resourceName The resource name which says what resource should be loaded.
// *
// * @throws std::runtime_error if the archive entry wasn't found
// */
// CLodStream(const CLodArchiveLoader * loader, const std::string & resourceName);
/**
* Opens a lod stream. It will close any currently opened file stream.
*
* @param loader The archive loader object which knows about the structure of the archive format.
* @param resourceName The resource name which says what resource should be loaded.
*
* @throws std::runtime_error if the archive entry wasn't found
*/
void open(const CLodArchiveLoader * loader, const std::string & resourceName);
// /**
// * Opens a lod stream. It will close any currently opened file stream.
// *
// * @param loader The archive loader object which knows about the structure of the archive format.
// * @param resourceName The resource name which says what resource should be loaded.
// *
// * @throws std::runtime_error if the archive entry wasn't found
// */
// void open(const CLodArchiveLoader * loader, const std::string & resourceName);
/**
* Reads n bytes from the stream into the data buffer.
*
* Warning: You can't read just a part of the archive entry if it's a decompressed one. So reading the total size always is
* recommended unless you really know what you're doing e.g. reading from a video stream.
*
* @param data A pointer to the destination data array.
* @param size The number of bytes to read.
* @return the number of bytes read actually.
*
* @throws std::runtime_error if the file decompression was not successful
*/
si64 read(ui8 * data, si64 size);
// /**
// * Reads n bytes from the stream into the data buffer.
// *
// * Warning: You can't read just a part of the archive entry if it's a decompressed one. So reading the total size always is
// * recommended unless you really know what you're doing e.g. reading from a video stream.
// *
// * @param data A pointer to the destination data array.
// * @param size The number of bytes to read.
// * @return the number of bytes read actually.
// *
// * @throws std::runtime_error if the file decompression was not successful
// */
// si64 read(ui8 * data, si64 size);
/**
* Seeks the internal read pointer to the specified position.
*
* @param position The read position from the beginning.
* @return the position actually moved to, -1 on error.
*/
si64 seek(si64 position);
// /**
// * Seeks the internal read pointer to the specified position.
// *
// * @param position The read position from the beginning.
// * @return the position actually moved to, -1 on error.
// */
// si64 seek(si64 position);
/**
* Gets the current read position in the stream.
*
* @return the read position.
*/
si64 tell();
// /**
// * Gets the current read position in the stream.
// *
// * @return the read position.
// */
// si64 tell();
/**
* Skips delta numbers of bytes.
*
* @param delta The count of bytes to skip.
* @return the count of bytes skipped actually.
*/
si64 skip(si64 delta);
// /**
// * Skips delta numbers of bytes.
// *
// * @param delta The count of bytes to skip.
// * @return the count of bytes skipped actually.
// */
// si64 skip(si64 delta);
/**
* Gets the length in bytes of the stream.
*
* @return the length in bytes of the stream.
*/
si64 getSize();
// /**
// * Gets the length in bytes of the stream.
// *
// * @return the length in bytes of the stream.
// */
// si64 getSize();
/**
* Closes the stream and releases any system resources associated with the stream explicitely.
*/
void close();
// /**
// * Closes the stream and releases any system resources associated with the stream explicitely.
// */
// void close();
private:
//private:
/** The file stream for reading from the LOD archive. */
CFileInputStream fileStream;
// /** The file stream for reading from the LOD archive. */
// std::unique_ptr<CInputStream> fileStream;
/** The archive entry which specifies the length, offset,... of the entry. */
const ArchiveEntry * archiveEntry;
};
// /** Offset of data in input stream. Used if input stream represents whole file*/
// size_t offset;
// /** Size of our data in input stream. */
// size_t size;
//};

View File

@ -2,36 +2,69 @@
#include "CResourceLoader.h"
#include "CFileInfo.h"
#include "CLodArchiveLoader.h"
#include "CFilesystemLoader.h"
CResourceLoader * CResourceLoaderFactory::resourceLoader = nullptr;
//For filesystem initialization
#include "../JsonNode.h"
#include "../GameConstants.h"
#include "../VCMIDirs.h"
ResourceIdentifier::ResourceIdentifier()
//experimental support for ERA-style mods. Requires custom config in mod directory
#define ENABLE_ERA_FILESYSTEM
CResourceLoader * CResourceHandler::resourceLoader = nullptr;
CResourceLoader * CResourceHandler::initialLoader = nullptr;
ResourceID::ResourceID()
:type(EResType::OTHER)
{
}
ResourceIdentifier::ResourceIdentifier(const std::string & name, EResType type) : name(name), type(type)
ResourceID::ResourceID(const std::string & name)
{
boost::to_upper(this->name);
CFileInfo info(name);
setName(info.getStem());
setType(info.getType());
}
std::string ResourceIdentifier::getName() const
ResourceID::ResourceID(const std::string & name, EResType::Type type)
{
setName(name);
setType(type);
}
ResourceID::ResourceID(const std::string & prefix, const std::string & name, EResType::Type type)
{
setName(name);
this->name = prefix + this->name;
setType(type);
}
std::string ResourceID::getName() const
{
return name;
}
EResType ResourceIdentifier::getType() const
EResType::Type ResourceID::getType() const
{
return type;
}
void ResourceIdentifier::setName(const std::string & name)
void ResourceID::setName(const std::string & name)
{
this->name = name;
size_t dotPos = this->name.find_last_of("/.");
if(dotPos != std::string::npos && this->name[dotPos] == '.')
this->name.erase(dotPos);
// strangely enough but this line takes 40-50% of filesystem loading time
boost::to_upper(this->name);
}
void ResourceIdentifier::setType(EResType type)
void ResourceID::setType(EResType::Type type)
{
this->type = type;
}
@ -43,13 +76,13 @@ CResourceLoader::CResourceLoader()
CResourceLoader::~CResourceLoader()
{
// Delete all loader objects
BOOST_FOREACH ( ISimpleResourceLoader* it, loaders)
BOOST_FOREACH ( auto & it, loaders)
{
delete it;
}
}
std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceIdentifier & resourceIdent) const
std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceID & resourceIdent) const
{
auto resource = resources.find(resourceIdent);
@ -66,31 +99,60 @@ std::unique_ptr<CInputStream> CResourceLoader::load(const ResourceIdentifier & r
return locator.getLoader()->load(locator.getResourceName());
}
bool CResourceLoader::existsResource(const ResourceIdentifier & resourceIdent) const
std::pair<std::unique_ptr<ui8[]>, ui64> CResourceLoader::loadData(const ResourceID & resourceIdent) const
{
auto stream = load(resourceIdent);
std::unique_ptr<ui8[]> data(new ui8[stream->getSize()]);
size_t readSize = stream->read(data.get(), stream->getSize());
assert(readSize == stream->getSize());
return std::make_pair(std::move(data), stream->getSize());
}
ResourceLocator CResourceLoader::getResource(const ResourceID & resourceIdent) const
{
auto resource = resources.find(resourceIdent);
if (resource == resources.end())
return ResourceLocator(nullptr, "");
return resource->second.back();
}
std::string CResourceLoader::getResourceName(const ResourceID & resourceIdent) const
{
auto locator = getResource(resourceIdent);
if (locator.getLoader())
return locator.getLoader()->getOrigin() + '/' + locator.getResourceName();
return "";
}
bool CResourceLoader::existsResource(const ResourceID & resourceIdent) const
{
// Check if resource is registered
return resources.find(resourceIdent) != resources.end();
}
void CResourceLoader::addLoader(ISimpleResourceLoader * loader)
void CResourceLoader::addLoader(std::string mountPoint, ISimpleResourceLoader * loader)
{
loaders.push_back(loader);
loaders.insert(loader);
// Get entries and add them to the resources list
const std::list<std::string> & entries = loader->getEntries();
boost::to_upper(mountPoint);
BOOST_FOREACH (const std::string & entry, entries)
{
CFileInfo file(entry);
// Create identifier and locator and add them to the resources list
ResourceIdentifier ident(file.getStem(), file.getType());
ResourceID ident(mountPoint, file.getStem(), file.getType());
ResourceLocator locator(loader, entry);
resources[ident].push_back(locator);
}
}
CResourceLoader * CResourceLoaderFactory::getInstance()
CResourceLoader * CResourceHandler::get()
{
if(resourceLoader != nullptr)
{
@ -105,10 +167,10 @@ CResourceLoader * CResourceLoaderFactory::getInstance()
}
}
void CResourceLoaderFactory::setInstance(CResourceLoader * resourceLoader)
{
CResourceLoaderFactory::resourceLoader = resourceLoader;
}
//void CResourceLoaderFactory::setInstance(CResourceLoader * resourceLoader)
//{
// CResourceLoaderFactory::resourceLoader = resourceLoader;
//}
ResourceLocator::ResourceLocator(ISimpleResourceLoader * loader, const std::string & resourceName)
: loader(loader), resourceName(resourceName)
@ -126,11 +188,11 @@ std::string ResourceLocator::getResourceName() const
return resourceName;
}
EResType EResTypeHelper::getTypeFromExtension(std::string extension)
EResType::Type EResTypeHelper::getTypeFromExtension(std::string extension)
{
boost::to_upper(extension);
static const std::map<std::string, EResType> stringToRes =
static const std::map<std::string, EResType::Type> stringToRes =
boost::assign::map_list_of
(".TXT", EResType::TEXT)
(".JSON", EResType::TEXT)
@ -146,12 +208,14 @@ EResType EResTypeHelper::getTypeFromExtension(std::string extension)
(".PNG", EResType::IMAGE)
(".TGA", EResType::IMAGE)
(".WAV", EResType::SOUND)
(".82M", EResType::SOUND)
(".SMK", EResType::VIDEO)
(".BIK", EResType::VIDEO)
(".MJPG", EResType::VIDEO)
(".MP3", EResType::MUSIC)
(".OGG", EResType::MUSIC)
(".LOD", EResType::ARCHIVE)
(".PAC", EResType::ARCHIVE)
(".VID", EResType::ARCHIVE)
(".SND", EResType::ARCHIVE)
(".VCGM1", EResType::CLIENT_SAVEGAME)
@ -164,13 +228,11 @@ EResType EResTypeHelper::getTypeFromExtension(std::string extension)
return iter->second;
}
std::string EResTypeHelper::getEResTypeAsString(EResType type)
std::string EResTypeHelper::getEResTypeAsString(EResType::Type type)
{
#define MAP_ENUM(value) (EResType::value, #value)
#define MAP_ENUM(value) (EResType::value, "value")
static const std::map<EResType, std::string> stringToRes = boost::assign::map_list_of
MAP_ENUM(ANY)
static const std::map<EResType::Type, std::string> stringToRes = boost::assign::map_list_of
MAP_ENUM(TEXT)
MAP_ENUM(ANIMATION)
MAP_ENUM(MASK)
@ -193,5 +255,80 @@ std::string EResTypeHelper::getEResTypeAsString(EResType type)
assert(iter != stringToRes.end());
return iter->second;
}
void CResourceHandler::initialize()
{
//temporary filesystem that will be used to initialize main one.
//used to solve several case-sensivity issues like Mp3 vs MP3
initialLoader = new CResourceLoader;
resourceLoader = new CResourceLoader;
auto rootDir = new CFilesystemLoader(GameConstants::DATA_DIR, 3);
initialLoader->addLoader("GLOBAL/", rootDir);
initialLoader->addLoader("ALL/", rootDir);
auto userDir = rootDir;
//add local directory to "ALL" but only if it differs from root dir (true for linux)
if (GameConstants::DATA_DIR != GVCMIDirs.UserPath)
{
userDir = new CFilesystemLoader(GVCMIDirs.UserPath, 3);
initialLoader->addLoader("ALL/", userDir);
}
//create "LOCAL" dir with current userDir (may be same as rootDir)
initialLoader->addLoader("LOCAL/", userDir);
}
void CResourceHandler::loadFileSystem(const std::string fsConfigURI)
{
const JsonNode fsConfig(initialLoader->getResourceName(ResourceID(fsConfigURI, EResType::TEXT)));
BOOST_FOREACH(auto & mountPoint, fsConfig["filesystem"].Struct())
{
BOOST_FOREACH(auto & entry, mountPoint.second.Vector())
{
tlog5 << "loading resource at " << entry["path"].String() << ": ";
std::string filename = initialLoader->getResourceName(entry["path"].String());
if (!filename.empty())
{
if (entry["type"].String() == "dir")
{
int depth = 16;
if (!entry["depth"].isNull())
depth = entry["depth"].Float();
resourceLoader->addLoader(mountPoint.first, new CFilesystemLoader(filename, depth));
}
if (entry["type"].String() == "file")
resourceLoader->addLoader(mountPoint.first, new CLodArchiveLoader(filename));
tlog5 << "OK\n";
}
else
tlog5 << "Not found\n";
}
}
}
void CResourceHandler::loadModsFilesystems()
{
#ifdef ENABLE_ERA_FILESYSTEM
auto iterator = initialLoader->getIterator([](const ResourceID & ident)
{
return ident.getType() == EResType::TEXT
&& boost::algorithm::starts_with(ident.getName(), "ALL/MODS/")
&& boost::algorithm::ends_with(ident.getName(), "FILESYSTEM");
});
while (iterator.hasNext())
{
tlog1 << "Found mod filesystem: " << iterator->getName() << "\n";
loadFileSystem(iterator->getName());
++iterator;
}
#endif
}

View File

@ -13,6 +13,7 @@
#include "CInputStream.h"
class CResourceLoader;
class ResourceLocator;
class ISimpleResourceLoader;
@ -23,47 +24,56 @@ class ISimpleResourceLoader;
*
* Text: .txt .json
* Animation: .def
* Mask: .msk
* Mask: .msk .msg
* Campaign: .h3c
* Map: .h3m
* Font: .fnt
* Image: .bmp, .jpg, .pcx, .png, .tga
* Sound: .wav
* Sound: .wav .82m
* Video: .smk, .bik .mjpg
* Music: .mp3, .ogg
* Archive: .lod, .snd, .vid
* Archive: .lod, .snd, .vid .pac
* Savegame: .v*gm1
*/
enum EResType
namespace EResType
{
ANY,
TEXT,
ANIMATION,
MASK,
CAMPAIGN,
MAP,
FONT,
IMAGE,
VIDEO,
SOUND,
MUSIC,
ARCHIVE,
CLIENT_SAVEGAME,
LIB_SAVEGAME,
SERVER_SAVEGAME,
OTHER
};
enum Type
{
TEXT,
ANIMATION,
MASK,
CAMPAIGN,
MAP,
FONT,
IMAGE,
VIDEO,
SOUND,
MUSIC,
ARCHIVE,
CLIENT_SAVEGAME,
LIB_SAVEGAME,
SERVER_SAVEGAME,
OTHER
};
}
/**
* A struct which identifies a resource clearly.
*/
class DLL_LINKAGE ResourceIdentifier
class DLL_LINKAGE ResourceID
{
public:
/**
* Default c-tor.
*/
ResourceIdentifier();
ResourceID();
/**
* Ctor. Can be used to implicitly create indentifier for resource loading
*
* @param name The resource name including extension.
*/
ResourceID(const std::string & fullName);
/**
* Ctor.
@ -71,7 +81,7 @@ public:
* @param name The resource name.
* @param type The resource type. A constant from the enumeration EResType.
*/
ResourceIdentifier(const std::string & name, EResType type);
ResourceID(const std::string & name, EResType::Type type);
/**
* Compares this object with a another resource identifier.
@ -79,7 +89,7 @@ public:
* @param other The other resource identifier.
* @return Returns true if both are equally, false if not.
*/
inline bool operator==(ResourceIdentifier const & other) const
inline bool operator==(ResourceID const & other) const
{
return name == other.name && type == other.type;
}
@ -96,7 +106,7 @@ public:
*
* @return the type of the identifier
*/
EResType getType() const;
EResType::Type getType() const;
/**
* Sets the name of the identifier.
@ -110,8 +120,19 @@ public:
*
* @param type the type of the identifier.
*/
void setType(EResType type);
void setType(EResType::Type type);
protected:
/**
* Ctor for usage strictly in resourceLoader for some speedup
*
* @param prefix Prefix of ths filename, already in upper case
* @param name The resource name.
* @param type The resource type. A constant from the enumeration EResType.
*/
ResourceID(const std::string & prefix, const std::string & name, EResType::Type type);
friend class CResourceLoader;
private:
/** Specifies the resource name. No extension so .pcx and .png can override each other, always in upper case. **/
std::string name;
@ -120,7 +141,7 @@ private:
* Specifies the resource type. EResType::OTHER if not initialized.
* Required to prevent conflicts if files with different types (e.g. text and image) have the same name.
*/
EResType type;
EResType::Type type;
};
namespace std
@ -128,17 +149,17 @@ namespace std
/**
* Template specialization for std::hash.
*/
template <>
class hash<ResourceIdentifier>
{
template <>
class hash<ResourceID>
{
public:
/**
* Generates a hash value for the resource identifier object.
*
* @param resourceIdent The object from which a hash value should be generated.
* @return the generated hash value
*/
size_t operator()(const ResourceIdentifier & resourceIdent) const
/**
* Generates a hash value for the resource identifier object.
*
* @param resourceIdent The object from which a hash value should be generated.
* @return the generated hash value
*/
size_t operator()(const ResourceID & resourceIdent) const
{
return hash<string>()(resourceIdent.getName()) ^ hash<int>()(static_cast<int>(resourceIdent.getType()));
}
@ -151,7 +172,67 @@ public:
*/
class DLL_LINKAGE CResourceLoader : public boost::noncopyable
{
typedef std::unordered_map<ResourceID, std::list<ResourceLocator> > ResourcesMap;
public:
/// class for iterating over all available files/Identifiers
/// can be created via CResourceLoader::getIterator
template <typename Comparator, typename Iter>
class Iterator
{
public:
/// find next available item.
Iterator& operator++()
{
assert(begin != end);
begin++;
findNext();
return *this;
}
bool hasNext()
{
return begin != end;
}
/// get identifier of current item
const ResourceID & operator* () const
{
assert(begin != end);
return begin->first;
}
/// get identifier of current item
const ResourceID * operator -> () const
{
assert(begin != end);
return &begin->first;
}
protected:
Iterator(Iter begin, Iter end, Comparator comparator):
begin(begin),
end(end),
comparator(comparator)
{
//find first applicable item
findNext();
}
friend class CResourceLoader;
private:
Iter begin;
Iter end;
Comparator comparator;
void findNext()
{
while (begin != end && !comparator(begin->first))
begin++;
}
};
CResourceLoader();
/**
@ -167,7 +248,35 @@ public:
*
* @throws std::runtime_error if the resource doesn't exists
*/
std::unique_ptr<CInputStream> load(const ResourceIdentifier & resourceIdent) const;
std::unique_ptr<CInputStream> load(const ResourceID & resourceIdent) const;
/// temporary member to ease transition to new filesystem classes
std::pair<std::unique_ptr<ui8[]>, ui64> loadData(const ResourceID & resourceIdent) const;
/**
* Get resource locator for this identifier
*
* @param resourceIdent This parameter identifies the resource to load.
* @return resource locator for this resource or empty one if resource was not found
*/
ResourceLocator getResource(const ResourceID & resourceIdent) const;
/// returns real name of file in filesystem. Not usable for archives
std::string getResourceName(const ResourceID & resourceIdent) const;
/// return size of file or 0 if not found
/**
* Get iterator for looping all files matching filter
* Notes:
* - iterating over all files may be slow. Use with caution
* - all filenames are in upper case
*
* @param filter functor with signature bool(ResourceIdentifier) used to check if this file is required
* @return resource locator for this resource or empty one if resource was not found
*/
template<typename Comparator>
Iterator<Comparator, ResourcesMap::const_iterator> getIterator(Comparator filter) const
{
return Iterator<Comparator, ResourcesMap::const_iterator>(resources.begin(), resources.end(), filter);
}
/**
* Tests whether the specified resource exists.
@ -175,17 +284,19 @@ public:
* @param resourceIdent the resource which should be checked
* @return true if the resource exists, false if not
*/
bool existsResource(const ResourceIdentifier & resourceIdent) const;
bool existsResource(const ResourceID & resourceIdent) const;
/**
* Adds a simple resource loader to the loaders list and its entries to the resources list.
*
* The loader object will be destructed when this resource loader is destructed.
* Don't delete it manually.
* Same loader can be added multiple times (with different mount point)
*
* @param mountPoint prefix that will be added to all files in this loader
* @param loader The simple resource loader object to add
*/
void addLoader(ISimpleResourceLoader * loader);
void addLoader(std::string mountPoint, ISimpleResourceLoader * loader);
private:
@ -193,10 +304,10 @@ private:
* Contains lists of same resources which can be accessed uniquely by an
* resource identifier.
*/
std::unordered_map<ResourceIdentifier, std::list<ResourceLocator> > resources;
ResourcesMap resources;
/** A list of resource loader objects */
std::list<ISimpleResourceLoader *> loaders;
std::set<ISimpleResourceLoader *> loaders;
};
/**
@ -209,7 +320,7 @@ private:
*
* This class is not thread-safe. Make sure nobody is calling getInstance while somebody else is calling setInstance.
*/
class DLL_LINKAGE CResourceLoaderFactory
class DLL_LINKAGE CResourceHandler
{
public:
/**
@ -219,18 +330,30 @@ public:
*
* @return Returns an instance of resource loader.
*/
static CResourceLoader * getInstance();
static CResourceLoader * get();
/**
* Sets an instance of resource loader.
* Creates instance of resource loader.
* Will not fill filesystem with data
*
* @param resourceLoader An instance of resource loader.
*/
static void setInstance(CResourceLoader * resourceLoader);
static void initialize();
/**
* Will load all filesystem data from Json data at this path (config/filesystem.json)
*/
static void loadFileSystem(const std::string fsConfigURI);
/**
* Experimental. Checks all subfolders of MODS directory for presence of ERA-style mods
* If this directory has filesystem.json file it will be added to resources
*/
static void loadModsFilesystems();
private:
/** Instance of resource loader */
static CResourceLoader * resourceLoader;
static CResourceLoader * initialLoader;
};
/**
@ -284,7 +407,7 @@ public:
* @param extension The extension string e.g. .BMP, .PNG
* @return Returns a EResType enum object
*/
static EResType getTypeFromExtension(std::string extension);
static EResType::Type getTypeFromExtension(std::string extension);
/**
* Gets the EResType as a string representation.
@ -292,5 +415,5 @@ public:
* @param type the EResType
* @return the type as a string representation
*/
static std::string getEResTypeAsString(EResType type);
static std::string getEResTypeAsString(EResType::Type type);
};

View File

@ -1,14 +1,16 @@
#include "StdInc.h"
#include "ISimpleResourceLoader.h"
#include "CMemoryStream.h"
#include <zlib.h>
std::pair<ui8*, size_t> ISimpleResourceLoader::decompressFile(ui8 * in, size_t size, size_t realSize)
std::pair<ui8*, size_t> ISimpleResourceLoader::decompress(ui8 * in, size_t size, size_t realSize)
{
std::pair<ui8*, size_t> retError(nullptr, 0);
//realSize was not set. Use compressed size as basisto gen something usable
if (realSize == 0)
realSize = 16 * 1024;
realSize = size * 2;
std::unique_ptr<ui8[]> out(new ui8[realSize]);
@ -42,6 +44,10 @@ std::pair<ui8*, size_t> ISimpleResourceLoader::decompressFile(ui8 * in, size_t s
// Run inflate() on input until output buffer not full
do
{
//TODO: check if inflate have any special mode for inflating (e.g Z_BLOCK)
//campaigns which consist from several blocks (campaign header + every map)
//technically .h3c consists from multiple cancatenated gz streams
//inflatings them separately can be useful for campaigns loading
strm.avail_out = realSize - lastPosOut;
strm.next_out = out.get() + lastPosOut;
ret = inflate(&strm, Z_NO_FLUSH);
@ -49,15 +55,12 @@ std::pair<ui8*, size_t> ISimpleResourceLoader::decompressFile(ui8 * in, size_t s
bool breakLoop = false;
switch (ret)
{
case Z_STREAM_END:
case Z_STREAM_END: //end decompression
breakLoop = true;
case Z_OK: //decompress next chunk
break;
case Z_NEED_DICT:
ret = Z_DATA_ERROR;
case Z_DATA_ERROR:
inflateEnd(&strm);
return retError;
case Z_MEM_ERROR:
case Z_BUF_ERROR:
{
//not enough memory. Allocate bigger buffer and try again
realSize *= 2;
@ -65,6 +68,11 @@ std::pair<ui8*, size_t> ISimpleResourceLoader::decompressFile(ui8 * in, size_t s
std::copy(out.get(), out.get() + strm.total_out, newOut.get());
out.reset(newOut.release());
}
default:
ret = Z_DATA_ERROR;
inflateEnd(&strm);
return retError;
}
if(breakLoop)
@ -83,11 +91,14 @@ std::pair<ui8*, size_t> ISimpleResourceLoader::decompressFile(ui8 * in, size_t s
{
ret = inflateEnd(&strm);
//FIXMWE: duplicates previous switch block
switch (ret)
{
case Z_STREAM_END:
case Z_OK:
//TODO: trim buffer? may be too time consuming
return std::make_pair(out.release(), realSize - strm.avail_out);
case Z_MEM_ERROR:
case Z_BUF_ERROR:
{
//not enough memory. Allocate bigger buffer and try again

View File

@ -18,17 +18,18 @@
*/
class DLL_LINKAGE ISimpleResourceLoader
{
public:
/**
* Decompresses an archive entry.
*
* @param in A pointer to the compressed data array
* @param size The size of the compressed data array
* @param realSize The size of the decompressed real size of the entry or 0 if not known (slower)
* @param realSize - hint decompressed size (if known)
* @returns pair(decompressed data, size)
*/
static std::pair<ui8*, size_t> decompressFile(ui8 * in, size_t size, size_t realSize);
static std::pair<ui8*, size_t> decompress(ui8 * in, size_t size, size_t realSize = 0);
public:
/**
* Dtor.
*/
@ -55,4 +56,11 @@ public:
* @return Returns a list of all entries in the archive or (file) system.
*/
virtual std::list<std::string> getEntries() const =0;
/**
* Gets the origin of the loader.
*
* @return the file path to source of this loader
*/
virtual std::string getOrigin() const =0;
};

View File

@ -8,12 +8,12 @@ libvcmi_la_CXXFLAGS = @SDL_CFLAGS@ -DVCMI_DLL
libvcmi_la_SOURCES = \
../Global.h \
Filesystem/CBinaryReader.cpp \
Filesystem/CCompressedStream.cpp \
Filesystem/CFileInfo.cpp \
Filesystem/CFileInputStream.cpp \
Filesystem/CFilesystemLoader.cpp \
Filesystem/CLodArchiveLoader.cpp \
Filesystem/CLodStream.cpp \
Filesystem/CMemoryStream.cpp \
Filesystem/CMemoryStream.cpp \
Filesystem/CResourceLoader.cpp \
Filesystem/ISimpleResourceLoader.cpp \
BattleAction.cpp \

View File

@ -86,10 +86,10 @@ am__installdirs = "$(DESTDIR)$(pkglibdir)"
LTLIBRARIES = $(pkglib_LTLIBRARIES)
libvcmi_la_DEPENDENCIES =
am_libvcmi_la_OBJECTS = libvcmi_la-CBinaryReader.lo \
libvcmi_la-CFileInfo.lo libvcmi_la-CFileInputStream.lo \
libvcmi_la-CFilesystemLoader.lo \
libvcmi_la-CLodArchiveLoader.lo libvcmi_la-CLodStream.lo \
libvcmi_la-CMemoryStream.lo libvcmi_la-CResourceLoader.lo \
libvcmi_la-CCompressedStream.lo libvcmi_la-CFileInfo.lo \
libvcmi_la-CFileInputStream.lo libvcmi_la-CFilesystemLoader.lo \
libvcmi_la-CLodArchiveLoader.lo libvcmi_la-CMemoryStream.lo \
libvcmi_la-CResourceLoader.lo \
libvcmi_la-ISimpleResourceLoader.lo libvcmi_la-BattleAction.lo \
libvcmi_la-BattleState.lo libvcmi_la-CArtHandler.lo \
libvcmi_la-CBuildingHandler.lo libvcmi_la-CCampaignHandler.lo \
@ -301,12 +301,12 @@ libvcmi_la_CXXFLAGS = @SDL_CFLAGS@ -DVCMI_DLL
libvcmi_la_SOURCES = \
../Global.h \
Filesystem/CBinaryReader.cpp \
Filesystem/CCompressedStream.cpp \
Filesystem/CFileInfo.cpp \
Filesystem/CFileInputStream.cpp \
Filesystem/CFilesystemLoader.cpp \
Filesystem/CLodArchiveLoader.cpp \
Filesystem/CLodStream.cpp \
Filesystem/CMemoryStream.cpp \
Filesystem/CMemoryStream.cpp \
Filesystem/CResourceLoader.cpp \
Filesystem/ISimpleResourceLoader.cpp \
BattleAction.cpp \
@ -461,6 +461,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CBinaryReader.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CBuildingHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CCampaignHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CCompressedStream.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CConsoleHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CCreatureHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CCreatureSet.Plo@am__quote@
@ -475,7 +476,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CHeroHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CLodArchiveLoader.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CLodHandler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CLodStream.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CLogger.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CMapInfo.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvcmi_la-CMemoryStream.Plo@am__quote@
@ -523,6 +523,13 @@ libvcmi_la-CBinaryReader.lo: Filesystem/CBinaryReader.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CBinaryReader.lo `test -f 'Filesystem/CBinaryReader.cpp' || echo '$(srcdir)/'`Filesystem/CBinaryReader.cpp
libvcmi_la-CCompressedStream.lo: Filesystem/CCompressedStream.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CCompressedStream.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CCompressedStream.Tpo -c -o libvcmi_la-CCompressedStream.lo `test -f 'Filesystem/CCompressedStream.cpp' || echo '$(srcdir)/'`Filesystem/CCompressedStream.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CCompressedStream.Tpo $(DEPDIR)/libvcmi_la-CCompressedStream.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Filesystem/CCompressedStream.cpp' object='libvcmi_la-CCompressedStream.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CCompressedStream.lo `test -f 'Filesystem/CCompressedStream.cpp' || echo '$(srcdir)/'`Filesystem/CCompressedStream.cpp
libvcmi_la-CFileInfo.lo: Filesystem/CFileInfo.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CFileInfo.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CFileInfo.Tpo -c -o libvcmi_la-CFileInfo.lo `test -f 'Filesystem/CFileInfo.cpp' || echo '$(srcdir)/'`Filesystem/CFileInfo.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CFileInfo.Tpo $(DEPDIR)/libvcmi_la-CFileInfo.Plo
@ -551,13 +558,6 @@ libvcmi_la-CLodArchiveLoader.lo: Filesystem/CLodArchiveLoader.cpp
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CLodArchiveLoader.lo `test -f 'Filesystem/CLodArchiveLoader.cpp' || echo '$(srcdir)/'`Filesystem/CLodArchiveLoader.cpp
libvcmi_la-CLodStream.lo: Filesystem/CLodStream.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CLodStream.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CLodStream.Tpo -c -o libvcmi_la-CLodStream.lo `test -f 'Filesystem/CLodStream.cpp' || echo '$(srcdir)/'`Filesystem/CLodStream.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CLodStream.Tpo $(DEPDIR)/libvcmi_la-CLodStream.Plo
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='Filesystem/CLodStream.cpp' object='libvcmi_la-CLodStream.lo' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -c -o libvcmi_la-CLodStream.lo `test -f 'Filesystem/CLodStream.cpp' || echo '$(srcdir)/'`Filesystem/CLodStream.cpp
libvcmi_la-CMemoryStream.lo: Filesystem/CMemoryStream.cpp
@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libvcmi_la_CXXFLAGS) $(CXXFLAGS) -MT libvcmi_la-CMemoryStream.lo -MD -MP -MF $(DEPDIR)/libvcmi_la-CMemoryStream.Tpo -c -o libvcmi_la-CMemoryStream.lo `test -f 'Filesystem/CMemoryStream.cpp' || echo '$(srcdir)/'`Filesystem/CMemoryStream.cpp
@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libvcmi_la-CMemoryStream.Tpo $(DEPDIR)/libvcmi_la-CMemoryStream.Plo

View File

@ -15,6 +15,7 @@
#include "IGameEventsReceiver.h"
#include "CStopWatch.h"
#include "VCMIDirs.h"
#include "Filesystem/CResourceLoader.h"
/*
* VCMI_Lib.cpp, part of VCMI engine
@ -26,11 +27,7 @@
*
*/
class CLodHandler;
LibClasses * VLC = NULL;
DLL_LINKAGE CLodHandler *bitmaph = NULL,
*spriteh = NULL,
*bitmaph_ab = NULL;
DLL_LINKAGE VCMIDirs GVCMIDirs;
@ -166,6 +163,12 @@ void LibClasses::init()
{
CStopWatch pomtime;
CResourceHandler::initialize();
CResourceHandler::loadFileSystem("ALL/config/filesystem.json");
CResourceHandler::loadModsFilesystems();
tlog0<<"\tFile system handler: "<<pomtime.getDiff()<<std::endl;
generaltexth = new CGeneralTextHandler;
generaltexth->load();
tlog0<<"\tGeneral text handler: "<<pomtime.getDiff()<<std::endl;
@ -236,20 +239,6 @@ void LibClasses::makeNull()
LibClasses::LibClasses()
{
//load .lod archives
if(!spriteh) //don't reload lods if we are starting a secoond game
{
CStopWatch pomtime;
spriteh = new CLodHandler();
spriteh->init(GameConstants::DATA_DIR + "/Data/H3sprite.lod", GameConstants::DATA_DIR + "/Sprites");
bitmaph = new CLodHandler;
bitmaph->init(GameConstants::DATA_DIR + "/Data/H3bitmap.lod", GameConstants::DATA_DIR + "/Data");
bitmaph_ab = new CLodHandler();
bitmaph_ab->init(GameConstants::DATA_DIR + "/Data/H3ab_bmp.lod", GameConstants::DATA_DIR + "/Data");
tlog0<<"Loading .lod files: "<<pomtime.getDiff()<<std::endl;
}
//init pointers to handlers
makeNull();
}

View File

@ -10,7 +10,6 @@
*
*/
class CLodHandler;
class CArtHandler;
class CHeroHandler;
class CCreatureHandler;
@ -55,7 +54,6 @@ public:
};
extern DLL_LINKAGE LibClasses * VLC;
extern DLL_LINKAGE CLodHandler * bitmaph, *spriteh, *bitmaph_ab;
DLL_LINKAGE void loadToIt(std::string &dest, const std::string &src, int &iter, int mode);
DLL_LINKAGE void loadToIt(si32 &dest, const std::string &src, int &iter, int mode);

View File

@ -1,10 +1,11 @@
#include "StdInc.h"
#include "map.h"
#include "Filesystem/CResourceLoader.h"
#include "Filesystem/CCompressedStream.h"
#include "CObjectHandler.h"
#include "CDefObjInfoHandler.h"
#include "VCMI_Lib.h"
#include <zlib.h>
#include <boost/crc.hpp>
#include "CLodHandler.h"
#include "CArtHandler.h"
@ -502,18 +503,19 @@ void Mapa::addBlockVisTiles(CGObjectInstance * obj)
Mapa::Mapa(std::string filename)
:grailPos(-1, -1, -1), grailRadious(0)
{
int mapsize = 0;
tlog0<<"Opening map file: "<<filename<<"\t "<<std::flush;
std::unique_ptr<CInputStream> compressed(CResourceHandler::get()->load(ResourceID(filename, EResType::MAP)));
std::unique_ptr<CInputStream> decompressed(new CCompressedStream(compressed, true));
//load file and decompress
ui8 * initTable = CLodHandler::getUnpackedFile(filename, &mapsize);
size_t mapSize = decompressed->getSize();
std::unique_ptr<ui8[]> data(new ui8 [mapSize] );
decompressed->read(data.get(), mapSize);
tlog0<<"done."<<std::endl;
initFromBytes(initTable, mapsize);
delete [] initTable;
initFromBytes(data.get(), mapSize);
}
Mapa::Mapa()

View File

@ -1,5 +1,6 @@
#include "StdInc.h"
#include "../lib/Filesystem/CResourceLoader.h"
#include "../lib/CCampaignHandler.h"
#include "../lib/CThreadHelper.h"
#include "../lib/Connection.h"
@ -312,25 +313,16 @@ CGameHandler * CVCMIServer::initGhFromHostingConnection(CConnection &c)
CGameHandler *gh = new CGameHandler();
StartInfo si;
c >> si; //get start options
int problem;
#ifdef _MSC_VER
FILE *f;
problem = fopen_s(&f,si.mapname.c_str(),"r");
#else
FILE * f = fopen(si.mapname.c_str(),"r");
problem = !f;
#endif
bool mapFound = CResourceHandler::get()->existsResource(ResourceID(si.mapname, EResType::MAP));
if(problem && si.mode == StartInfo::NEW_GAME) //TODO some checking for campaigns
if(!mapFound && si.mode == StartInfo::NEW_GAME) //TODO some checking for campaigns
{
c << ui8(problem); //WRONG!
c << ui8(1); //WRONG!
return NULL;
}
else
{
if(f)
fclose(f);
c << ui8(0); //OK!
}
@ -453,7 +445,7 @@ void CVCMIServer::loadGame()
CMapHeader dum;
StartInfo *si;
CLoadFile lf(fname + ".vlgm1");
CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::LIB_SAVEGAME)));
lf >> sig >> dum >> si;
tlog0 <<"Reading save signature"<<std::endl;
@ -466,7 +458,7 @@ void CVCMIServer::loadGame()
}
{
CLoadFile lf(fname + ".vsgm1");
CLoadFile lf(CResourceHandler::get()->getResourceName(ResourceID(fname, EResType::SERVER_SAVEGAME)));
lf >> gh;
}