Example #1
0
Gun* GunFactory::build(std::string const gunType, Ship* const ship, bool const isPlayer){
	FileLoader loader;
	std::map<std::string, XMLGunBlueprint> blueprints = loader.getGunBlueprints();

	if ( blueprints.find(gunType) == blueprints.end()) {
		std::runtime_error("Not an valid gun type");
	}

	XMLGunBlueprint blueprint = blueprints[gunType];
	BulletFactory* bulletFactory = new BulletFactory(this->fWorld, ship, blueprint.bullets);

	Gun* gun;
	// The direction the gun is pointed to
	if(isPlayer == true){
		// The player is up
		Direction direction("up");
		gun = new Gun(ship, direction, bulletFactory, blueprint);
	}else{
		// Enemies are down
		Direction direction("down");
		gun = new Gun(ship, direction, bulletFactory, blueprint);
	}

	return gun;
}
Example #2
0
bool Container::unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream)
{
	bool ret = Item::unserializeItemNode(f, node, propStream);

	if(ret){
		unsigned long type;
		NODE nodeItem = f.getChildNode(node, type);
		while(nodeItem){
			//load container items
			if(type == OTBM_ITEM){
				PropStream itemPropStream;
				f.getProps(nodeItem, itemPropStream);
				
				Item* item = Item::CreateItem(itemPropStream);
				if(!item){
					return false;
				}

				if(!item->unserializeItemNode(f, nodeItem, itemPropStream)){
					return false;
				}
				
				addItem(item);
			}
			else /*unknown type*/
				return false;

			nodeItem = f.getNextNode(nodeItem, type);
		}
		
		return true;
	}

	return false;
}
Example #3
0
bool Container::unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream)
{
    if(!Item::unserializeItemNode(f, node, propStream))
        return false;

    uint32_t type;
    for(NODE nodeItem = f.getChildNode(node, type); nodeItem; nodeItem = f.getNextNode(nodeItem, type))
    {
        //load container items
        if(type != OTBM_ITEM)
            return false;

        PropStream itemPropStream;
        f.getProps(nodeItem, itemPropStream);

        Item* item = Item::CreateItem(itemPropStream);
        if(!item)
            return false;

        if(!item->unserializeItemNode(f, nodeItem, itemPropStream))
            return false;

        addItem(item);
        updateItemWeight(item->getWeight());
    }

    return true;
}
bool DBSystem::LoadDBFile()
{
	do 
	{
		char*        pBuffer = NULL;
		unsigned int iLength = 0;
		if (!EngineSystem::LoadAppFile("resource/data/game.data", pBuffer, iLength))
		{
			LOGGERSYSTEM->LogFatal("Init DBSystem Failed, DB Data Invalid\n");
			return false;
		}

		std::string buffer = "";
		if (EngineSystem::IsAndroid480X800())
		{
			buffer = "d42fcd0a5e6145fd988b55dc0570bb82";
		}
		else
		{
			buffer = "3ecae97470b968ec37bb640246a425e9";
		}

		// 进行静态数据md5码校验
		std::string md5Key = MD5Crypto::md5(pBuffer, iLength);
		if (md5Key.compare(buffer) != 0)
		{
			delete []pBuffer;
			LOGGERSYSTEM->LogFatal("Init DBSystem Failed, DB Data Invalid2\n");
			return false;
		}

		// 保存到SD卡对应目录下面
		std::string dbFile = EngineSystem::GetDocumentDir()+"game.db";
		FileLoader loader;
		if (!loader.load((char*)dbFile.c_str(), FileLoader::_TYPED_CLEAR_WRITE_))
		{
			loader.unload();
			delete []pBuffer;
			return false;
		}

		loader.write(pBuffer, iLength);
		loader.unload();
		delete []pBuffer;

		int ret = sqlite3_open(dbFile.c_str(), &m_pSQLite);
		if (ret != SQLITE_OK)
		{
			LOGGERSYSTEM->LogFatal("Init DBSystem Failed, DBFile=%s\n", dbFile.c_str());
			return false;
		}

		return true;
	} 
	while(false);

	return false;
}
Example #5
0
void SimpleVolumeGenerator::generate( const FileLoader &loader,
				      const FieldSelector &selector,
				      CoordinateAdjuster &adjuster,
				      const ColorMap &colormap
) {
  
  if( selector.getFieldNum() < 4 ) {
    throw std::runtime_error("SimpleVolumeGenerator::4 indeces is needed at least.");
  }
  
  volume_->clear();

  // setting coordinates range
  const FileLoader::DataType &max_range = loader.getMaxRange();
  const FileLoader::DataType &min_range = loader.getMinRange();

  const double min_x = selector.getField( min_range, 0);
  const double min_y = selector.getField( min_range, 1);
  const double min_z = selector.getField( min_range, 2);
  
  const double dist_x = selector.getField( max_range, 0) - min_x;
  const double dist_y = selector.getField( max_range, 1) - min_y;
  const double dist_z = selector.getField( max_range, 2) - min_z;
  const double dist = std::max( dist_x, std::max( dist_y, dist_z ) );

  const double max_x = min_x + dist;
  const double max_y = min_y + dist;
  const double max_z = min_z + dist;

  adjuster.setRangeX( max_x, min_x );
  adjuster.setRangeY( max_y, min_y );
  adjuster.setRangeZ( max_z, min_z );

  // setting volume data
  for( FileLoader::DataContainerType::const_iterator it = loader.begin();
       it != loader.end();
       ++it ) {
    const FileLoader::DataType &data = *it;

    const double raw_x = selector.getField( data, 0 );
    const double raw_y = selector.getField( data, 1 );
    const double raw_z = selector.getField( data, 2 );
    
    const double x = adjuster.x(raw_x) * ( getVolume()->sizex() );
    const double y = adjuster.y(raw_y) * ( getVolume()->sizey() );
    const double z = adjuster.z(raw_z) * ( getVolume()->sizez() );
    
    double r, g, b, a;
    colormap.getColor( adjuster.x(raw_x), &r, &g, &b, &a );
    
    setVolumeElement
      ( 
       x, y, z,
       r * 255, g * 255, b * 255, a * 255);
  }
  
}
Example #6
0
int								main(int argc, char **argv)
{
    char Name = 'M';
    std::string taq = "TaquinA5_2.txt";
    if (argc == 3)
    {
        std::ifstream infile;
        infile.open(argv[2]);
        if (!infile.is_open())
        {
            std::cout << "Error: file <" << argv[2] << ">" << " not found" << std::endl;
            return (-1);
        }
        infile.close();
        taq = argv[2];
        FileLoader				F;
        std::string				S;
        Puzzle					P;
        SolutionGenerator		SG;
        short unsigned int**	Tab;
        clock_t					timeDeb, timeEnd;
        std::list<Puzzle>		OpenedList, ClosedList;
        int x = 0, y = 0, fg = -42;

        timeDeb = clock();
        DisplayLogo();
        F.LoadFile(taq.c_str(), S);
        std::istringstream		In(S);
        P.SetAlgo(Name);
        Tab = P.CreatePuzzle(S);
        std::list<Puzzle>::iterator FirstPuzzle;
        OpenedList.push_back(P);
        while (fg != 0 && !OpenedList.empty())
        {
            FirstPuzzle = OpenedList.begin();
            fg = Resume(FirstPuzzle, OpenedList, ClosedList, timeEnd);
            ProcessUp(FirstPuzzle, OpenedList, ClosedList);
            ProcessDown(FirstPuzzle, OpenedList, ClosedList);
            ProcessRight(FirstPuzzle, OpenedList, ClosedList);
            ProcessLeft(FirstPuzzle, OpenedList, ClosedList);

            (*FirstPuzzle).ClearListTab();
            ClosedList.push_back(*FirstPuzzle);
            OpenedList.erase(FirstPuzzle);
        }
        if (fg != 0)
            std::cout << "NO SOLUTION FOR THIS TAQUIN!!!" << std::endl;
        std::cout << "CLOSED LIST NUMBER OF CONTENTS	: \t\t[" << ClosedList.size() << "]"<< std::endl;
        std::cout << "TIME ELAPSED			: \t\t[" << static_cast<double>(timeEnd - timeDeb) << "] ms." << std::endl;
        ShowNbMoves();
        std::cout << "Cleaning..." << std::endl;
        Clean(OpenedList, ClosedList);
        std::cout << "Clean done" << std::endl;
    }
    return (0);
}
Example #7
0
void FileLoader::loadNext() {
	if (_queue->queries >= _queue->limit) return;
	for (FileLoader *i = _queue->start; i;) {
		if (i->loadPart()) {
			if (_queue->queries >= _queue->limit) return;
		} else {
			i = i->_next;
		}
	}
}
Example #8
0
void SDFShadowDemo::LoadSDFBuffer()
{
    const std::wstring sdfFile = L"testScene.sdf";
    FileLoader loader;
    loader.Open(FileSystem::getSingleton().GetModelsFolder() + sdfFile);
    auto ptr = loader.GetDataPtr();
    std::string sdfText(ptr);
    std::vector<std::string> lines;

    pystring::splitlines(sdfText, lines);
    std::string line0 = lines[0];
    std::vector<std::string> line0Split;
    pystring::split(line0, line0Split, " ");
    m_sdfParams.x = strtof(line0Split[0].c_str(), 0);
    m_sdfParams.y = strtof(line0Split[1].c_str(), 0);
    m_sdfParams.z = strtof(line0Split[2].c_str(), 0);
    m_sdfParams.w = strtof(lines[2].c_str(), 0);

    std::string line1 = lines[1];
    std::vector<std::string> line1Split;
    pystring::split(line1, line1Split, " ");
    m_sdfOrigin.x = strtof(line1Split[0].c_str(), 0);
    m_sdfOrigin.y = strtof(line1Split[1].c_str(), 0);
    m_sdfOrigin.z = strtof(line1Split[2].c_str(), 0);

    const auto SDFCount = m_sdfParams.x * m_sdfParams.y * m_sdfParams.z;
    for (auto i = 0; i < SDFCount; ++i)
    {
        f32 value = strtof(lines[3 + i].c_str(), 0);
        m_sdf.push_back(value);
    }

    Texture3dConfigDX11 texConfig;
    texConfig.SetDefaults();
    texConfig.SetWidth(static_cast<u32>(m_sdfParams.x));
    texConfig.SetHeight(static_cast<u32>(m_sdfParams.y));
    texConfig.SetDepth(static_cast<u32>(m_sdfParams.z));
    texConfig.SetFormat(DXGI_FORMAT_R32_FLOAT);

    D3D11_SUBRESOURCE_DATA data;
    data.pSysMem = &m_sdf[0];
    data.SysMemPitch = static_cast<u32>(sizeof(f32) * m_sdfParams.x);
    data.SysMemSlicePitch = static_cast<u32>(sizeof(f32) * m_sdfParams.x * m_sdfParams.y);

    ShaderResourceViewConfigDX11 srvConfig;
    srvConfig.SetFormat(DXGI_FORMAT_R32_FLOAT);
    srvConfig.SetViewDimensions(D3D11_SRV_DIMENSION_TEXTURE3D);
    D3D11_TEX3D_SRV srv;
    srv.MostDetailedMip = 0;
    srv.MipLevels = 1;
    srvConfig.SetTexture3D(srv);

    m_SDFTex3D = m_pRender->CreateTexture3D(&texConfig, &data, &srvConfig);
}
Example #9
0
void  Preprocessor::LoadFile(cc_string filename)
{
    FileLoader * loader = new FileLoader(filename.c_str());
    if (!loader->isLoad())
    {
        delete loader;
        return ;
    }
    m_Tokenizer.Init(filename, loader);

}
Example #10
0
bool Container::unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream)
{
	bool ret = Item::unserializeItemNode(f, node, propStream);

	if(ret){
		unsigned long type;
		NODE nodeItem = f.getChildNode(node, type);
		while(nodeItem){
			//load container items
			if(type == OTBM_ITEM){
				PropStream itemPropStream;
				f.getProps(nodeItem, itemPropStream);

				Item* item = Item::CreateItem(itemPropStream);
				if(!item){
					return false;
				}

				if(!item->unserializeItemNode(f, nodeItem, itemPropStream)){
					return false;
				}

				addItem(item);

				//deepness
				if (item->getContainer()){
					if (getParentContainer())
						item->getContainer()->setDeepness(getDeepness() + 1);
					else{ //we only update deepness when a container get inside of another, so it means that deepness is not updated
						setDeepness(1);
						item->getContainer()->setDeepness(2);
					}
				}

				updateAmountOfItems(item->getTotalAmountOfItemsInside());
				total_weight += item->getWeight();
				if(Container* parent_container = getParentContainer()) {
					parent_container->updateItemWeight(item->getWeight());

				}
			}
			else /*unknown type*/
				return false;

			nodeItem = f.getNextNode(nodeItem, type);
		}

		return true;
	}

	return false;
}
Example #11
0
void loadFile(
        FileLoader& loader,
        std::string path,
        std::function<void(std::string const&)> continuation)
{
        loader.loadFile(path, continuation);
}
Example #12
0
bool CachingFileLoader::Exists() {
	if (exists_ == -1) {
		lock_guard guard(backendMutex_);
		exists_ = backend_->Exists() ? 1 : 0;
	}
	return exists_ == 1;
}
Example #13
0
bool CachingFileLoader::IsDirectory() {
	if (isDirectory_ == -1) {
		lock_guard guard(backendMutex_);
		isDirectory_ = backend_->IsDirectory() ? 1 : 0;
	}
	return isDirectory_ == 1;
}
Example #14
0
SpriteFactory::SpriteFactory()
{
  FileLoader	loader;
  //   #ifdef _WIN32
  //   loader.setExtension(".dll");
  // #else
  loader.setExtension(".so");
  //#endif
  std::cout << "\033[34mLoad des libs Ships" << std::endl;
  loader.runInDirectory("libs/ships/", this->_shipLibs);
  std::cout << "Load des libs Weapons" << std::endl;
  loader.runInDirectory("libs/weapons/", this->_weaponLibs);
  std::cout << "Load des libs Decors" << std::endl;
  loader.runInDirectory("libs/decors/", this->_decorLibs);
  std::cout << "\033[39m";
}
Example #15
0
void loadFilePair(
        FileLoader& loader,
        std::string path1,
        std::string path2,
        std::function<void(std::string const&, std::string const&)> continuation)
{
        loader.loadFiles(path1, path2, continuation);
}
char* LocalPlayerDataManager::LoadDBFile(std::string fileName, long& length)
{
	FileLoader loader;
	if (!loader.load((char*)fileName.c_str(), FileLoader::_TYPED_READ_ONLY_))
	{
		loader.unload();
		return NULL;
	}

	length = loader.length();
	if (length <= (sizeof(char)*32+sizeof(int)))
	{
		loader.unload();
		return NULL;
	}
	
	// 读取文件信息
	char* pBuffer = new char[length+1];
	memset(pBuffer, 0, length+1);
	loader.read(pBuffer, length);
	loader.unload();

	// 先进行解密
	DBSYSTEM->XORBuffer((char*)DBSYSTEM->GetLocalDataEncryptionKey().c_str(), pBuffer, length);

	// 判断文件是否完整
	std::string md5Key = MD5Crypto::md5((unsigned char*)pBuffer, length-32);
	if (md5Key.compare(pBuffer+length-32) != 0)
	{
		delete[] pBuffer;
		return NULL;
	}

	return pBuffer;
}
Example #17
0
bool Container::unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream)
{
	bool ret = Item::unserializeItemNode(f, node, propStream);
	if (!ret) {
		return false;
	}

	uint32_t type;
	NODE nodeItem = f.getChildNode(node, type);
	while (nodeItem) {
		//load container items
		if (type != OTBM_ITEM) {
			// unknown type
			return false;
		}

		PropStream itemPropStream;
		if (!f.getProps(nodeItem, itemPropStream)) {
			return false;
		}

		Item* item = Item::CreateItem(itemPropStream);
		if (!item) {
			return false;
		}

		if (!item->unserializeItemNode(f, nodeItem, itemPropStream)) {
			return false;
		}

		addItem(item);
		totalWeight += item->getWeight();

		if (Container* parent_container = getParentContainer()) {
			parent_container->updateItemWeight(item->getWeight());
		}

		nodeItem = f.getNextNode(nodeItem, type);
	}
	return true;
}
Example #18
0
void __UmdReplace(std::string filepath) {
	// TODO: This should really go through Loaders, no?  What if it's an invalid file?

	// Only get system from disc0 seems have been enough.
	IFileSystem* currentUMD = pspFileSystem.GetSystem("disc0:");
	IFileSystem* currentISOBlock = pspFileSystem.GetSystem("umd0:");
	if (!currentUMD)
		return;

	FileLoader *loadedFile = ConstructFileLoader(filepath);

	IFileSystem* umd2;
	if (!loadedFile->Exists()) {
		delete loadedFile;
		return;
	}
	UpdateLoadedFile(loadedFile);

	if (loadedFile->IsDirectory()) {
		umd2 = new VirtualDiscFileSystem(&pspFileSystem, filepath);
	} else {
		auto bd = constructBlockDevice(loadedFile);
		if (!bd)
			return;
		umd2 = new ISOFileSystem(&pspFileSystem, bd);
		pspFileSystem.Remount(currentUMD, umd2);

		if (currentUMD != currentISOBlock) {
			// We mounted an ISO block system separately.
			IFileSystem *iso = new ISOBlockSystem(static_cast<ISOFileSystem *>(umd2));
			pspFileSystem.Remount(currentISOBlock, iso);
			delete currentISOBlock;
		}
	}
	delete currentUMD;

	// TODO Is this always correct if UMD was not activated?
	u32 notifyArg = PSP_UMD_PRESENT | PSP_UMD_READABLE | PSP_UMD_CHANGED;
	if (driveCBId != -1)
		__KernelNotifyCallback(driveCBId, notifyArg);
}
bool EngineSystem::LoadTempFile(char* pFileName, char*& pBuffer, unsigned int& iLength)
{
	assert(pFileName != NULL);
	assert(strlen(pFileName) > 0);

	std::string filepath = EngineSystem::GetDocumentDir();
	filepath += pFileName;

	FileLoader loader;
	if (!loader.load((char*)filepath.c_str(), FileLoader::_TYPED_READ_ONLY_))
		return false;

	// 读取文件内容
	iLength = loader.length();
	pBuffer = new char[iLength+1];
	memset(pBuffer, 0, iLength+1);
	loader.read(pBuffer, iLength);
	loader.unload();

	return true;
}
Example #20
0
void ShipFactory::buildStage(XMLStage stage){
	if(this->fWorld == nullptr){
		throw std::runtime_error("Can't build any ships because there is no World* avaible");
	}

	FileLoader loader;
	std::map<std::string, XMLShipBlueprint> blueprints = loader.getShipBlueprints();

	for(auto i : stage.ships){
		if ( blueprints.find(i.type) == blueprints.end()) {
			std::runtime_error("Not an valid ship type");
		}

		XMLShipBlueprint blueprint = blueprints.at(i.type);
		Vector location(i.x, i.y);

		Ship* ship = this->buildShip(location, blueprint, false);

		// Add the ship to the ships list
		this->fWorld->addShip(ship);
	}
}
Example #21
0
void Config::AddRecent(const std::string &file) {
	// Don't bother with this if the user disabled recents (it's -1).
	if (iMaxRecent <= 0)
		return;

	for (auto str = recentIsos.begin(); str != recentIsos.end(); ++str) {
#ifdef _WIN32
		if (!strcmpIgnore((*str).c_str(), file.c_str(), "\\", "/")) {
#else
		if (!strcmp((*str).c_str(), file.c_str())) {
#endif
			recentIsos.erase(str);
			recentIsos.insert(recentIsos.begin(), file);
			if ((int)recentIsos.size() > iMaxRecent)
				recentIsos.resize(iMaxRecent);
			return;
		}
	}
	recentIsos.insert(recentIsos.begin(), file);
	if ((int)recentIsos.size() > iMaxRecent)
		recentIsos.resize(iMaxRecent);
}

void Config::CleanRecent() {
	std::vector<std::string> cleanedRecent;
	for (size_t i = 0; i < recentIsos.size(); i++) {
		FileLoader *loader = ConstructFileLoader(recentIsos[i]);
		if (loader->Exists()) {
			// Make sure we don't have any redundant items.
			auto duplicate = std::find(cleanedRecent.begin(), cleanedRecent.end(), recentIsos[i]);
			if (duplicate == cleanedRecent.end()) {
				cleanedRecent.push_back(recentIsos[i]);
			}
		}
		delete loader;
	}
	recentIsos = cleanedRecent;
}
Example #22
0
bool ScriptSys::Init()
{
	m_IDIndex = 0;
	m_MainState = lua_open();
	luaL_openlibs( m_MainState );
	m_Holder = new ScriptHolder( m_MainState );
	m_Holder->Init();
	
	BuildFuncs();

	// test, add some scripts first.
	char file[512];
	for( int i = 0; i < SCRIPT_NUM; ++ i )
	{
		sprintf( file, "scripts\\%d.lua", i + 1 );
		FileLoader loader;
		loader.Load( file, FileLoader::BINARY );
		FileLoader::RawData data = loader.GetRawData();
		m_Holder->Add( file, (char*) data.buf, data.size );
	}

	return true;
}
Example #23
0
bool Container::unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream)
{
	if(Item::unserializeItemNode(f, node, propStream))
	{
		uint32_t type;
		NODE nodeItem = f.getChildNode(node, type);
		while(nodeItem)
		{
			//load container items
			if(type == OTBM_ITEM)
			{
				PropStream itemPropStream;
				f.getProps(nodeItem, itemPropStream);

				Item* item = Item::CreateItem(itemPropStream);
				if(!item)
					return false;

				if(!item->unserializeItemNode(f, nodeItem, itemPropStream))
					return false;

				addItem(item);
				totalWeight += item->getWeight();
				if(Container* parent = getParentContainer())
					parent->updateItemWeight(item->getWeight());
			}
			else/*unknown type*/
				return false;

			nodeItem = f.getNextNode(nodeItem, type);
		}

		return true;
	}

	return false;
}
Example #24
0
void QHexEdit::loadFromFile(const QString &path)
{
    QFileInfo fileInf(path);
    if (fileInf.size() > MAX_BINARY_FILE_SIZE)
    {
        QMessageBox::warning(this, ERROR_TOO_LARGE_BINARY_FILE_TITLE,
                             ERROR_TOO_LARGE_BINARY_FILE_MSG.arg(
                                 QString::number(fileInf.size())),
                             QMessageBox::Ok);
        return;
    }
    if (fileInf.size() > SCROLLED_BINARY_FILE_MAX_SIZE)
    {
        QMessageBox::warning(this, WARNING_LARGE_BINARY_FILE_TITLE,
                             WARNING_LARGE_BINARY_FILE_TEXT);
    }
    //Check if the file has already been opened
    //or it is not file at all
    if (getCurrentPath() == fileInf.filePath()
            || !fileInf.isFile())
    {
        return;
    }

    FileLoader *fLoader = new FileLoader();

    fLoader->openFile(fileInf.filePath());

    QByteArray arr;
    fLoader->loadToByteArray(arr);
    setCursorPosition(0);
    clearSelection();
    setData(arr);
    setCurrentPath(fileInf.filePath());
    fLoader->deleteLater();
}
Example #25
0
GpuShaderProgramID ShaderAsset::Refresh(FileLoader& loader)
{
    GpuShaderProgramID old = m_shaderProgram;

    char fullPath[SHADER_MAX_PATH_LENGTH];
    PrintFullPath(fullPath, sizeof fullPath, GetName());

    u8* data;
    u32 size;
    loader.Load(fullPath, &data, &size, Alloc, NULL);

    m_shaderProgram = m_device.ShaderProgramCreate((const char*)data, (size_t)size);

    free(data);

    m_refCountAndRefreshStatus |= REFRESH_STATUS_MASK;
    return old;
}
Example #26
0
ShaderAsset::ShaderAsset(GpuDevice& device, FileLoader& loader, const char* name)
    : m_link()

    , m_device(device)
    , m_shaderProgram(0)
    , m_refCountAndRefreshStatus(0)
{
    char fullPath[SHADER_MAX_PATH_LENGTH];
    PrintFullPath(fullPath, sizeof fullPath, name);

    u8* data;
    u32 size;
    loader.Load(fullPath, &data, &size, Alloc, NULL);

    m_shaderProgram = device.ShaderProgramCreate((const char*)data, (size_t)size);

    free(data);
}
Example #27
0
FILELOADER_ERRORS Items::loadFromOtb(const std::string& file)
{
	FileLoader f;
	if (!f.openFile(file.c_str(), "OTBI")) {
		return f.getError();
	}

	uint32_t type;
	NODE node = f.getChildNode(NO_NODE, type);

	PropStream props;
	if (f.getProps(node, props)) {
		//4 byte flags
		//attributes
		//0x01 = version data
		uint32_t flags;
		if (!props.read<uint32_t>(flags)) {
			return ERROR_INVALID_FORMAT;
		}

		uint8_t attr;
		if (!props.read<uint8_t>(attr)) {
			return ERROR_INVALID_FORMAT;
		}

		if (attr == ROOT_ATTR_VERSION) {
			uint16_t datalen;
			if (!props.read<uint16_t>(datalen)) {
				return ERROR_INVALID_FORMAT;
			}

			if (datalen != sizeof(VERSIONINFO)) {
				return ERROR_INVALID_FORMAT;
			}

			VERSIONINFO vi;
			if (!props.read(vi)) {
				return ERROR_INVALID_FORMAT;
			}

			Items::dwMajorVersion = vi.dwMajorVersion; //items otb format file version
			Items::dwMinorVersion = vi.dwMinorVersion; //client version
			Items::dwBuildNumber = vi.dwBuildNumber; //revision
		}
	}

	if (Items::dwMajorVersion == 0xFFFFFFFF) {
		std::cout << "[Warning - Items::loadFromOtb] items.otb using generic client version." << std::endl;
	} else if (Items::dwMajorVersion != 2) {
		std::cout << "Old version detected, a newer version of items.otb is required." << std::endl;
		return ERROR_INVALID_FORMAT;
	} else if (Items::dwMinorVersion < CLIENT_VERSION_800) {
		std::cout << "A newer version of items.otb is required." << std::endl;
		return ERROR_INVALID_FORMAT;
	}

	node = f.getChildNode(node, type);
	while (node != NO_NODE) {
		PropStream stream;
		if (!f.getProps(node, stream)) {
			return f.getError();
		}

		uint32_t flags;
		if (!stream.read<uint32_t>(flags)) {
			return ERROR_INVALID_FORMAT;
		}

		uint16_t serverId = 0;
		uint16_t clientId = 0;
		uint16_t speed = 0;
		uint16_t wareId = 0;
		uint8_t lightLevel = 0;
		uint8_t lightColor = 0;
		uint8_t alwaysOnTopOrder = 0;

		uint8_t attrib;
		while (stream.read<uint8_t>(attrib)) {
			uint16_t datalen;
			if (!stream.read<uint16_t>(datalen)) {
				return ERROR_INVALID_FORMAT;
			}

			switch (attrib) {
				case ITEM_ATTR_SERVERID: {
					if (datalen != sizeof(uint16_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint16_t>(serverId)) {
						return ERROR_INVALID_FORMAT;
					}

					if (serverId > 30000 && serverId < 30100) {
						serverId -= 30000;
					}
					break;
				}

				case ITEM_ATTR_CLIENTID: {
					if (datalen != sizeof(uint16_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint16_t>(clientId)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}

				case ITEM_ATTR_SPEED: {
					if (datalen != sizeof(uint16_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint16_t>(speed)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}

				case ITEM_ATTR_LIGHT2: {
					if (datalen != sizeof(lightBlock2)) {
						return ERROR_INVALID_FORMAT;
					}

					lightBlock2 lb2;
					if (!stream.read(lb2)) {
						return ERROR_INVALID_FORMAT;
					}

					lightLevel = static_cast<uint8_t>(lb2.lightLevel);
					lightColor = static_cast<uint8_t>(lb2.lightColor);
					break;
				}

				case ITEM_ATTR_TOPORDER: {
					if (datalen != sizeof(uint8_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint8_t>(alwaysOnTopOrder)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}

				case ITEM_ATTR_WAREID: {
					if (datalen != sizeof(uint16_t)) {
						return ERROR_INVALID_FORMAT;
					}

					if (!stream.read<uint16_t>(wareId)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}

				default: {
					//skip unknown attributes
					if (!stream.skip(datalen)) {
						return ERROR_INVALID_FORMAT;
					}
					break;
				}
			}
		}

		reverseItemMap.emplace(clientId, serverId);

		// store the found item
		if (serverId >= items.size()) {
			items.resize(serverId + 1);
		}
		ItemType& iType = items[serverId];

		iType.group = static_cast<itemgroup_t>(type);
		switch (type) {
			case ITEM_GROUP_CONTAINER:
				iType.type = ITEM_TYPE_CONTAINER;
				break;
			case ITEM_GROUP_DOOR:
				//not used
				iType.type = ITEM_TYPE_DOOR;
				break;
			case ITEM_GROUP_MAGICFIELD:
				//not used
				iType.type = ITEM_TYPE_MAGICFIELD;
				break;
			case ITEM_GROUP_TELEPORT:
				//not used
				iType.type = ITEM_TYPE_TELEPORT;
				break;
			case ITEM_GROUP_NONE:
			case ITEM_GROUP_GROUND:
			case ITEM_GROUP_SPLASH:
			case ITEM_GROUP_FLUID:
			case ITEM_GROUP_CHARGES:
			case ITEM_GROUP_DEPRECATED:
				break;
			default:
				return ERROR_INVALID_FORMAT;
		}

		iType.blockSolid = hasBitSet(FLAG_BLOCK_SOLID, flags);
		iType.blockProjectile = hasBitSet(FLAG_BLOCK_PROJECTILE, flags);
		iType.blockPathFind = hasBitSet(FLAG_BLOCK_PATHFIND, flags);
		iType.hasHeight = hasBitSet(FLAG_HAS_HEIGHT, flags);
		iType.useable = hasBitSet(FLAG_USEABLE, flags);
		iType.pickupable = hasBitSet(FLAG_PICKUPABLE, flags);
		iType.moveable = hasBitSet(FLAG_MOVEABLE, flags);
		iType.stackable = hasBitSet(FLAG_STACKABLE, flags);

		iType.alwaysOnTop = hasBitSet(FLAG_ALWAYSONTOP, flags);
		iType.isVertical = hasBitSet(FLAG_VERTICAL, flags);
		iType.isHorizontal = hasBitSet(FLAG_HORIZONTAL, flags);
		iType.isHangable = hasBitSet(FLAG_HANGABLE, flags);
		iType.allowDistRead = hasBitSet(FLAG_ALLOWDISTREAD, flags);
		iType.rotatable = hasBitSet(FLAG_ROTATABLE, flags);
		iType.canReadText = hasBitSet(FLAG_READABLE, flags);
		iType.lookThrough = hasBitSet(FLAG_LOOKTHROUGH, flags);
		// iType.walkStack = !hasBitSet(FLAG_FULLTILE, flags);
		iType.forceUse = hasBitSet(FLAG_FORCEUSE, flags);

		iType.id = serverId;
		iType.clientId = clientId;
		iType.speed = speed;
		iType.lightLevel = lightLevel;
		iType.lightColor = lightColor;
		iType.wareId = wareId;
		iType.alwaysOnTopOrder = alwaysOnTopOrder;

		node = f.getNextNode(node, type);
	}

	items.shrink_to_fit();
	return ERROR_NONE;
}
Example #28
0
int
main(int argc, char** argv)
{
  ArgumentParser argp(argc, argv, "uw:h:c:");
  if ( argp.num_items() != 2 )
  {
    print_usage(argp.program_name());
    printf("\nInvalid number of files given\n\n");
    return -1;
  }

  const char *fn_in  = argp.items()[0];
  const char *fn_out = argp.items()[1];

  char* fn_out_copy = strdup(fn_out);
  
  printf("Input file:  %s\n"
	 "Output file: %s\n",
	 fn_in, fn_out);
  
  // strip off extension
  char *t = strtok(fn_out_copy, ".");
  if (NULL == t)
  {
    printf("invalid filename");
    return -2;
  }

  char* ext_out;
  while(NULL != t)
  {
    ext_out = t;
    t = strtok(NULL, ".");
  }

  FileLoader *fl = NULL;
  Writer* writer = NULL;

  if ( argp.has_arg("u") )
  {
    if (argp.has_arg("c") && argp.has_arg("w") && argp.has_arg("h"))
    {
      fl = new FileLoader(colorspace_by_name(argp.arg("c")), fn_in,
			  argp.parse_int("w"), argp.parse_int("h"));
      printf("Input image: %s, %lix%li\n", argp.arg("c"),
	     argp.parse_int("w"), argp.parse_int("h"));
    }
    else
    {
      printf("You have to supply all of -w, -h, -c when using -u.\n");
      return -3;
    }
  }
  else
  {
    fl = new FileLoader(fn_in);
  }

  fl->open();
  fl->start();

  unsigned char *tmpbuf = malloc_buffer(YUV422_PLANAR, fl->pixel_width(), fl->pixel_height());
  convert(fl->colorspace(), YUV422_PLANAR, fl->buffer(), tmpbuf,
	  fl->pixel_width(), fl->pixel_height());

  // FvRaw
  if ( 0 == strcmp(ext_out, "raw") )
  {
    printf("Format for out file %s is FvRaw\n", fn_out);
    writer = new FvRawWriter();
  }
#ifdef HAVE_LIBJPEG
  // JPEG
  else if ( 0 == strcmp(ext_out, "jpeg") || 0 == strcmp(ext_out, "jpg") )
  { 
    printf("Format for out file %s is Jpeg\n", fn_out);
    writer = new JpegWriter();
  }
#endif
#ifdef HAVE_LIBPNG
  // PNG
  else if ( 0 == strcmp(ext_out, "png") )
  {
    printf("Format for out file %s is PNG\n", fn_out);
    writer = new PNGWriter();
  }
#endif
  // PNM
  else if ( 0 == strcmp(ext_out, "pnm") )
  {
    printf("Format for out file %s is PNM\n", fn_out);
    writer = new PNMWriter(PNM_PPM);
  }
  else
  {
    printf("Unknown output file format\n");
    exit(-2);
  }

  writer->set_filename(fn_out);
  writer->set_dimensions(fl->pixel_width(), fl->pixel_height());
  writer->set_buffer(YUV422_PLANAR, tmpbuf);
  writer->write();

  free(fn_out_copy);

  delete fl;
  delete writer;

  free(tmpbuf);
  
  return 0;
}
Example #29
0
bool IOMap::loadMap(Map* map, const std::string& identifier)
{
	FileLoader f;
	if(!f.openFile(identifier.c_str(), false, true))
	{
		std::stringstream ss;
		ss << "Could not open the file " << identifier << ".";
		setLastErrorString(ss.str());
		return false;
	}

	uint32_t type = 0;
	NODE root = f.getChildNode((NODE)NULL, type);

	PropStream propStream;
	if(!f.getProps(root, propStream))
	{
		setLastErrorString("Could not read root property.");
		return false;
	}

	OTBM_root_header* rootHeader;
	if(!propStream.GET_STRUCT(rootHeader))
	{
		setLastErrorString("Could not read header.");
		return false;
	}

	uint32_t headerVersion = rootHeader->version;
	if(headerVersion <= 0)
	{
		//In otbm version 1 the count variable after splashes/fluidcontainers and stackables
		//are saved as attributes instead, this solves alot of problems with items
		//that is changed (stackable/charges/fluidcontainer/splash) during an update.
		setLastErrorString("This map needs to be upgraded by using the latest map editor version to be able to load correctly.");
		return false;
	}

	if(headerVersion > 2)
	{
		setLastErrorString("Unknown OTBM version detected.");
		return false;
	}

	uint32_t headerMajorItems = rootHeader->majorVersionItems;
	if(headerMajorItems < 3)
	{
		setLastErrorString("This map needs to be upgraded by using the latest map editor version to be able to load correctly.");
		return false;
	}

	if(headerMajorItems > (uint32_t)Items::dwMajorVersion)
	{
		setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required.");
		return false;
	}

	uint32_t headerMinorItems = rootHeader->minorVersionItems;
	if(headerMinorItems < CLIENT_VERSION_810)
	{
		setLastErrorString("This map needs an updated items.otb.");
		return false;
	}

	if(headerMinorItems > (uint32_t)Items::dwMinorVersion)
		setLastErrorString("This map needs an updated items.otb.");

	std::cout << "> Map size: " << rootHeader->width << "x" << rootHeader->height << "." << std::endl;
	map->mapWidth = rootHeader->width;
	map->mapHeight = rootHeader->height;

	NODE nodeMap = f.getChildNode(root, type);
	if(type != OTBM_MAP_DATA)
	{
		setLastErrorString("Could not read data node.");
		return false;
	}

	if(!f.getProps(nodeMap, propStream))
	{
		setLastErrorString("Could not read map data attributes.");
		return false;
	}

	std::string tmp;
	uint8_t attribute;
	while(propStream.GET_UCHAR(attribute))
	{
		switch(attribute)
		{
			case OTBM_ATTR_DESCRIPTION:
			{
				if(!propStream.GET_STRING(tmp))
				{
					setLastErrorString("Invalid description tag.");
					return false;
				}

				map->descriptions.push_back(tmp);
				break;
			}
			case OTBM_ATTR_EXT_SPAWN_FILE:
			{
				if(!propStream.GET_STRING(tmp))
				{
					setLastErrorString("Invalid spawnfile tag.");
					return false;
				}

				map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1);
				map->spawnfile += tmp;
				break;
			}
			case OTBM_ATTR_EXT_HOUSE_FILE:
			{
				if(!propStream.GET_STRING(tmp))
				{
					setLastErrorString("Invalid housefile tag.");
					return false;
				}

				map->housefile = identifier.substr(0, identifier.rfind('/') + 1);
				map->housefile += tmp;
				break;
			}
			default:
			{
				setLastErrorString("Unknown header node.");
				return false;
			}
		}
	}

	std::cout << "> Map descriptions: " << std::endl;
	for(StringVec::iterator it = map->descriptions.begin(); it != map->descriptions.end(); ++it)
		std::cout << (*it) << std::endl;

	NODE nodeMapData = f.getChildNode(nodeMap, type);
	while(nodeMapData != NO_NODE)
	{
		if(f.getError() != ERROR_NONE)
		{
			setLastErrorString("Invalid map node.");
			return false;
		}

		if(type == OTBM_TILE_AREA)
		{
			if(!f.getProps(nodeMapData, propStream))
			{
				setLastErrorString("Invalid map node.");
				return false;
			}

			OTBM_Destination_coords* area_coord;
			if(!propStream.GET_STRUCT(area_coord))
			{
				setLastErrorString("Invalid map node.");
				return false;
			}

			int32_t base_x = area_coord->_x, base_y = area_coord->_y, base_z = area_coord->_z;
			NODE nodeTile = f.getChildNode(nodeMapData, type);
			while(nodeTile != NO_NODE)
			{
				if(f.getError() != ERROR_NONE)
				{
					setLastErrorString("Could not read node data.");
					return false;
				}

				if(type == OTBM_TILE || type == OTBM_HOUSETILE)
				{
					if(!f.getProps(nodeTile, propStream))
					{
						setLastErrorString("Could not read node data.");
						return false;
					}

					OTBM_Tile_coords* tileCoord;
					if(!propStream.GET_STRUCT(tileCoord))
					{
						setLastErrorString("Could not read tile position.");
						return false;
					}

					Tile* tile = NULL;
					Item* groundItem = NULL;
					uint32_t tileflags = 0;

					uint16_t px = base_x + tileCoord->_x, py = base_y + tileCoord->_y, pz = base_z;
					House* house = NULL;
					if(type == OTBM_HOUSETILE)
					{
						uint32_t _houseid;
						if(!propStream.GET_ULONG(_houseid))
						{
							std::stringstream ss;
							ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not read house id.";

							setLastErrorString(ss.str());
							return false;
						}

						house = Houses::getInstance().getHouse(_houseid, true);
						if(!house)
						{
							std::stringstream ss;
							ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not create house id: " << _houseid;

							setLastErrorString(ss.str());
							return false;
						}

						tile = new HouseTile(px, py, pz, house);
						house->addTile(static_cast<HouseTile*>(tile));
					}

					//read tile attributes
					uint8_t attribute;
					while(propStream.GET_UCHAR(attribute))
					{
						switch(attribute)
						{
							case OTBM_ATTR_TILE_FLAGS:
							{
								uint32_t flags;
								if(!propStream.GET_ULONG(flags))
								{
									std::stringstream ss;
									ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to read tile flags.";

									setLastErrorString(ss.str());
									return false;
								}

								if((flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE)
									tileflags |= TILESTATE_PROTECTIONZONE;
								else if((flags & TILESTATE_NOPVPZONE) == TILESTATE_NOPVPZONE)
									tileflags |= TILESTATE_NOPVPZONE;
								else if((flags & TILESTATE_PVPZONE) == TILESTATE_PVPZONE)
									tileflags |= TILESTATE_PVPZONE;

								if((flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT)
									tileflags |= TILESTATE_NOLOGOUT;

								if((flags & TILESTATE_REFRESH) == TILESTATE_REFRESH)
								{
									if(house)
										std::cout << "[x:" << px << ", y:" << py << ", z:" << pz << "] House tile flagged as refreshing!";

									tileflags |= TILESTATE_REFRESH;
								}

								break;
							}

							case OTBM_ATTR_ITEM:
							{
								Item* item = Item::CreateItem(propStream);
								if(!item)
								{
									std::stringstream ss;
									ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item.";

									setLastErrorString(ss.str());
									return false;
								}

								if(house && item->isMoveable())
								{
									std::cout << "[Warning - IOMap::loadMap] Movable item in house: " << house->getHouseId();
									std::cout << ", item type: " << item->getID() << ", at position " << px << "/" << py << "/";
									std::cout << pz << std::endl;

									delete item;
									item = NULL;
								}
								else if(tile)
								{
									tile->__internalAddThing(item);
									item->__startDecaying();
									item->setLoadedFromMap(true);
								}
								else if(item->isGroundTile())
								{
									if(groundItem)
										delete groundItem;

									groundItem = item;
								}
								else
								{
									tile = createTile(groundItem, item, px, py, pz);
									tile->__internalAddThing(item);

									item->__startDecaying();
									item->setLoadedFromMap(true);
								}

								break;
							}

							default:
							{
								std::stringstream ss;
								ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown tile attribute.";

								setLastErrorString(ss.str());
								return false;
							}
						}
					}

					NODE nodeItem = f.getChildNode(nodeTile, type);
					while(nodeItem)
					{
						if(type == OTBM_ITEM)
						{
							PropStream propStream;
							f.getProps(nodeItem, propStream);

							Item* item = Item::CreateItem(propStream);
							if(!item)
							{
								std::stringstream ss;
								ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item.";

								setLastErrorString(ss.str());
								return false;
							}

							if(item->unserializeItemNode(f, nodeItem, propStream))
							{
								if(house && item->isMoveable())
								{
									std::cout << "[Warning - IOMap::loadMap] Movable item in house: ";
									std::cout << house->getHouseId() << ", item type: " << item->getID();
									std::cout << ", pos " << px << "/" << py << "/" << pz << std::endl;

									delete item;
									item = NULL;
								}
								else if(tile)
								{
									tile->__internalAddThing(item);
									item->__startDecaying();
									item->setLoadedFromMap(true);
								}
								else if(item->isGroundTile())
								{
									if(groundItem)
										delete groundItem;

									groundItem = item;
								}
								else
								{
									tile = createTile(groundItem, item, px, py, pz);
									tile->__internalAddThing(item);

									item->__startDecaying();
									item->setLoadedFromMap(true);
								}
							}
							else
							{
								std::stringstream ss;
								ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to load item " << item->getID() << ".";
								setLastErrorString(ss.str());

								delete item;
								item = NULL;
								return false;
							}
						}
						else
						{
							std::stringstream ss;
							ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown node type.";
							setLastErrorString(ss.str());
						}

						nodeItem = f.getNextNode(nodeItem, type);
					}

					if(!tile)
						tile = createTile(groundItem, NULL, px, py, pz);

					tile->setFlag((tileflags_t)tileflags);
					map->setTile(px, py, pz, tile);
				}
				else
				{
					setLastErrorString("Unknown tile node.");
					return false;
				}

				nodeTile = f.getNextNode(nodeTile, type);
			}
		}
		else if(type == OTBM_TOWNS)
		{
			NODE nodeTown = f.getChildNode(nodeMapData, type);
			while(nodeTown != NO_NODE)
			{
				if(type == OTBM_TOWN)
				{
					if(!f.getProps(nodeTown, propStream))
					{
						setLastErrorString("Could not read town data.");
						return false;
					}

					uint32_t townId = 0;
					if(!propStream.GET_ULONG(townId))
					{
						setLastErrorString("Could not read town id.");
						return false;
					}

					Town* town = Towns::getInstance().getTown(townId);
					if(!town)
					{
						town = new Town(townId);
						Towns::getInstance().addTown(townId, town);
					}

					std::string townName = "";
					if(!propStream.GET_STRING(townName))
					{
						setLastErrorString("Could not read town name.");
						return false;
					}

					town->setName(townName);
					OTBM_Destination_coords *town_coords;
					if(!propStream.GET_STRUCT(town_coords))
					{
						setLastErrorString("Could not read town coordinates.");
						return false;
					}

					town->setTemplePos(Position(town_coords->_x, town_coords->_y, town_coords->_z));
				}
				else
				{
					setLastErrorString("Unknown town node.");
					return false;
				}

				nodeTown = f.getNextNode(nodeTown, type);
			}
		}
		else if(type == OTBM_WAYPOINTS && headerVersion > 1)
		{
			NODE nodeWaypoint = f.getChildNode(nodeMapData, type);
			while(nodeWaypoint != NO_NODE)
			{
				if(type == OTBM_WAYPOINT)
				{
					if(!f.getProps(nodeWaypoint, propStream))
					{
						setLastErrorString("Could not read waypoint data.");
						return false;
					}

					std::string name;
					if(!propStream.GET_STRING(name))
					{
						setLastErrorString("Could not read waypoint name.");
						return false;
					}

					OTBM_Destination_coords* waypoint_coords;
					if(!propStream.GET_STRUCT(waypoint_coords))
					{
						setLastErrorString("Could not read waypoint coordinates.");
						return false;
					}

					map->waypoints.addWaypoint(WaypointPtr(new Waypoint(name,
						Position(waypoint_coords->_x, waypoint_coords->_y, waypoint_coords->_z))));
				}
				else
				{
					setLastErrorString("Unknown waypoint node.");
					return false;
				}

				nodeWaypoint = f.getNextNode(nodeWaypoint, type);
			}
		}
		else
		{
			setLastErrorString("Unknown map node.");
			return false;
		}

		nodeMapData = f.getNextNode(nodeMapData, type);
	}

	return true;
}
Example #30
0
bool IOMap::loadMap(Map* map, const std::string& identifier)
{
	int64_t start = OTSYS_TIME();

	FileLoader f;
	if (!f.openFile(identifier.c_str(), "OTBM")) {
		std::ostringstream ss;
		ss << "Could not open the file " << identifier << '.';
		setLastErrorString(ss.str());
		return false;
	}

	uint32_t type;
	PropStream propStream;

	NODE root = f.getChildNode(nullptr, type);
	if (!f.getProps(root, propStream)) {
		setLastErrorString("Could not read root property.");
		return false;
	}

	const OTBM_root_header* root_header;
	if (!propStream.readStruct(root_header)) {
		setLastErrorString("Could not read header.");
		return false;
	}

	uint32_t headerVersion = root_header->version;
	if (headerVersion <= 0) {
		//In otbm version 1 the count variable after splashes/fluidcontainers and stackables
		//are saved as attributes instead, this solves alot of problems with items
		//that is changed (stackable/charges/fluidcontainer/splash) during an update.
		setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly.");
		return false;
	}

	if (headerVersion > 2) {
		setLastErrorString("Unknown OTBM version detected.");
		return false;
	}

	if (root_header->majorVersionItems < 3) {
		setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly.");
		return false;
	}

	if (root_header->majorVersionItems > Items::dwMajorVersion) {
		setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required.");
		return false;
	}

	if (root_header->minorVersionItems < CLIENT_VERSION_810) {
		setLastErrorString("This map needs to be updated.");
		return false;
	}

	if (root_header->minorVersionItems > Items::dwMinorVersion) {
		std::cout << "[Warning - IOMap::loadMap] This map needs an updated items.otb." << std::endl;
	}

	std::cout << "> Map size: " << root_header->width << "x" << root_header->height << '.' << std::endl;
	map->width = root_header->width;
	map->height = root_header->height;

	NODE nodeMap = f.getChildNode(root, type);
	if (type != OTBM_MAP_DATA) {
		setLastErrorString("Could not read data node.");
		return false;
	}

	if (!f.getProps(nodeMap, propStream)) {
		setLastErrorString("Could not read map data attributes.");
		return false;
	}

	std::string mapDescription;
	std::string tmp;

	uint8_t attribute;
	while (propStream.read<uint8_t>(attribute)) {
		switch (attribute) {
			case OTBM_ATTR_DESCRIPTION:
				if (!propStream.readString(mapDescription)) {
					setLastErrorString("Invalid description tag.");
					return false;
				}
				break;

			case OTBM_ATTR_EXT_SPAWN_FILE:
				if (!propStream.readString(tmp)) {
					setLastErrorString("Invalid spawn tag.");
					return false;
				}

				map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1);
				map->spawnfile += tmp;
				break;

			case OTBM_ATTR_EXT_HOUSE_FILE:
				if (!propStream.readString(tmp)) {
					setLastErrorString("Invalid house tag.");
					return false;
				}

				map->housefile = identifier.substr(0, identifier.rfind('/') + 1);
				map->housefile += tmp;
				break;

			default:
				setLastErrorString("Unknown header node.");
				return false;
		}
	}

	NODE nodeMapData = f.getChildNode(nodeMap, type);
	while (nodeMapData != NO_NODE) {
		if (f.getError() != ERROR_NONE) {
			setLastErrorString("Invalid map node.");
			return false;
		}

		if (type == OTBM_TILE_AREA) {
			if (!f.getProps(nodeMapData, propStream)) {
				setLastErrorString("Invalid map node.");
				return false;
			}

			const OTBM_Destination_coords* area_coord;
			if (!propStream.readStruct(area_coord)) {
				setLastErrorString("Invalid map node.");
				return false;
			}

			int32_t base_x = area_coord->x;
			int32_t base_y = area_coord->y;
			int32_t base_z = area_coord->z;

			NODE nodeTile = f.getChildNode(nodeMapData, type);
			while (nodeTile != NO_NODE) {
				if (f.getError() != ERROR_NONE) {
					setLastErrorString("Could not read node data.");
					return false;
				}

				if (type != OTBM_TILE && type != OTBM_HOUSETILE) {
					setLastErrorString("Unknown tile node.");
					return false;
				}

				if (!f.getProps(nodeTile, propStream)) {
					setLastErrorString("Could not read node data.");
					return false;
				}

				const OTBM_Tile_coords* tile_coord;
				if (!propStream.readStruct(tile_coord)) {
					setLastErrorString("Could not read tile position.");
					return false;
				}

				uint16_t px = base_x + tile_coord->x;
				uint16_t py = base_y + tile_coord->y;
				uint16_t pz = base_z;

				bool isHouseTile = false;
				House* house = nullptr;
				Tile* tile = nullptr;
				Item* ground_item = nullptr;
				uint32_t tileflags = TILESTATE_NONE;

				if (type == OTBM_HOUSETILE) {
					uint32_t houseId;
					if (!propStream.read<uint32_t>(houseId)) {
						std::ostringstream ss;
						ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not read house id.";
						setLastErrorString(ss.str());
						return false;
					}

					house = map->houses.addHouse(houseId);
					if (!house) {
						std::ostringstream ss;
						ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not create house id: " << houseId;
						setLastErrorString(ss.str());
						return false;
					}

					tile = new HouseTile(px, py, pz, house);
					house->addTile(reinterpret_cast<HouseTile*>(tile));
					isHouseTile = true;
				}

				//read tile attributes
				while (propStream.read<uint8_t>(attribute)) {
					switch (attribute) {
						case OTBM_ATTR_TILE_FLAGS: {
							uint32_t flags;
							if (!propStream.read<uint32_t>(flags)) {
								std::ostringstream ss;
								ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to read tile flags.";
								setLastErrorString(ss.str());
								return false;
							}

							if ((flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) {
								tileflags |= TILESTATE_PROTECTIONZONE;
							} else if ((flags & TILESTATE_NOPVPZONE) == TILESTATE_NOPVPZONE) {
								tileflags |= TILESTATE_NOPVPZONE;
							} else if ((flags & TILESTATE_PVPZONE) == TILESTATE_PVPZONE) {
								tileflags |= TILESTATE_PVPZONE;
							}

							if ((flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT) {
								tileflags |= TILESTATE_NOLOGOUT;
							}
							break;
						}

						case OTBM_ATTR_ITEM: {
							Item* item = Item::CreateItem(propStream);
							if (!item) {
								std::ostringstream ss;
								ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item.";
								setLastErrorString(ss.str());
								return false;
							}

							if (isHouseTile && item->isMoveable()) {
								std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << px << ", y: " << py << ", z: " << pz << "]." << std::endl;
								delete item;
							} else {
								if (item->getItemCount() <= 0) {
									item->setItemCount(1);
								}

								if (tile) {
									tile->internalAddThing(item);
									item->startDecaying();
									item->setLoadedFromMap(true);
								} else if (item->isGroundTile()) {
									delete ground_item;
									ground_item = item;
								} else {
									tile = createTile(ground_item, item, px, py, pz);
									tile->internalAddThing(item);
									item->startDecaying();
									item->setLoadedFromMap(true);
								}
							}
							break;
						}

						default:
							std::ostringstream ss;
							ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown tile attribute.";
							setLastErrorString(ss.str());
							return false;
					}
				}

				NODE nodeItem = f.getChildNode(nodeTile, type);
				while (nodeItem) {
					if (type != OTBM_ITEM) {
						std::ostringstream ss;
						ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown node type.";
						setLastErrorString(ss.str());
						return false;
					}

					PropStream stream;
					if (!f.getProps(nodeItem, stream)) {
						setLastErrorString("Invalid item node.");
						return false;
					}

					Item* item = Item::CreateItem(stream);
					if (!item) {
						std::ostringstream ss;
						ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item.";
						setLastErrorString(ss.str());
						return false;
					}

					if (!item->unserializeItemNode(f, nodeItem, stream)) {
						std::ostringstream ss;
						ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to load item " << item->getID() << '.';
						setLastErrorString(ss.str());
						delete item;
						return false;
					}

					if (isHouseTile && item->isMoveable()) {
						std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << px << ", y: " << py << ", z: " << pz << "]." << std::endl;
						delete item;
					} else {
						if (item->getItemCount() <= 0) {
							item->setItemCount(1);
						}

						if (tile) {
							tile->internalAddThing(item);
							item->startDecaying();
							item->setLoadedFromMap(true);
						} else if (item->isGroundTile()) {
							delete ground_item;
							ground_item = item;
						} else {
							tile = createTile(ground_item, item, px, py, pz);
							tile->internalAddThing(item);
							item->startDecaying();
							item->setLoadedFromMap(true);
						}
					}

					nodeItem = f.getNextNode(nodeItem, type);
				}

				if (!tile) {
					tile = createTile(ground_item, nullptr, px, py, pz);
				}

				tile->setFlag(static_cast<tileflags_t>(tileflags));

				map->setTile(px, py, pz, tile);

				nodeTile = f.getNextNode(nodeTile, type);
			}
		} else if (type == OTBM_TOWNS) {
			NODE nodeTown = f.getChildNode(nodeMapData, type);
			while (nodeTown != NO_NODE) {
				if (type != OTBM_TOWN) {
					setLastErrorString("Unknown town node.");
					return false;
				}

				if (!f.getProps(nodeTown, propStream)) {
					setLastErrorString("Could not read town data.");
					return false;
				}

				uint32_t townId;
				if (!propStream.read<uint32_t>(townId)) {
					setLastErrorString("Could not read town id.");
					return false;
				}

				Town* town = map->towns.getTown(townId);
				if (!town) {
					town = new Town(townId);
					map->towns.addTown(townId, town);
				}

				std::string townName;
				if (!propStream.readString(townName)) {
					setLastErrorString("Could not read town name.");
					return false;
				}

				town->setName(townName);

				const OTBM_Destination_coords* town_coords;
				if (!propStream.readStruct(town_coords)) {
					setLastErrorString("Could not read town coordinates.");
					return false;
				}

				town->setTemplePos(Position(town_coords->x, town_coords->y, town_coords->z));

				nodeTown = f.getNextNode(nodeTown, type);
			}
		} else if (type == OTBM_WAYPOINTS && headerVersion > 1) {
			NODE nodeWaypoint = f.getChildNode(nodeMapData, type);
			while (nodeWaypoint != NO_NODE) {
				if (type != OTBM_WAYPOINT) {
					setLastErrorString("Unknown waypoint node.");
					return false;
				}

				if (!f.getProps(nodeWaypoint, propStream)) {
					setLastErrorString("Could not read waypoint data.");
					return false;
				}

				std::string name;
				if (!propStream.readString(name)) {
					setLastErrorString("Could not read waypoint name.");
					return false;
				}

				const OTBM_Destination_coords* waypoint_coords;
				if (!propStream.readStruct(waypoint_coords)) {
					setLastErrorString("Could not read waypoint coordinates.");
					return false;
				}

				map->waypoints[name] = Position(waypoint_coords->x, waypoint_coords->y, waypoint_coords->z);

				nodeWaypoint = f.getNextNode(nodeWaypoint, type);
			}
		} else {
			setLastErrorString("Unknown map node.");
			return false;
		}

		nodeMapData = f.getNextNode(nodeMapData, type);
	}

	std::cout << "> Map loading time: " << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl;
	return true;
}