void SpriteManager::saveSpr(std::string fileName) { if(!m_loaded) stdext::throw_exception("failed to save, spr is not loaded"); try { FileStreamPtr fin = g_resources.createFile(fileName); if(!fin) stdext::throw_exception(stdext::format("failed to open file '%s' for write", fileName)); fin->cache(); fin->addU32(m_signature); if(g_game.getFeature(Otc::GameSpritesU32)) fin->addU32(m_spritesCount); else fin->addU16(m_spritesCount); uint32 offset = fin->tell(); uint32 spriteAddress = offset + 4 * m_spritesCount; for(int i = 1; i <= m_spritesCount; i++) fin->addU32(0); for(int i = 1; i <= m_spritesCount; i++) { m_spritesFile->seek((i - 1) * 4 + m_spritesOffset); uint32 fromAdress = m_spritesFile->getU32(); if(fromAdress != 0) { fin->seek(offset + (i - 1) * 4); fin->addU32(spriteAddress); fin->seek(spriteAddress); m_spritesFile->seek(fromAdress); fin->addU8(m_spritesFile->getU8()); fin->addU8(m_spritesFile->getU8()); fin->addU8(m_spritesFile->getU8()); uint16 dataSize = m_spritesFile->getU16(); fin->addU16(dataSize); char spriteData[SPRITE_DATA_SIZE]; m_spritesFile->read(spriteData, dataSize); fin->write(spriteData, dataSize); spriteAddress = fin->tell(); } //TODO: Check for overwritten sprites. } fin->flush(); fin->close(); } catch(std::exception& e) { g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what())); } }
SoundFilePtr SoundFile::loadSoundFile(const std::string& filename) { FileStreamPtr file = g_resources.openFile(filename); if(!file) { logTraceError("unable to open ", filename); return nullptr; } // cache file buffer to avoid lags from hard drive file->cache(); char magic[4]; file->read(magic, 4); file->seek(0); SoundFilePtr soundFile; if(strncmp(magic, "OggS", 4) == 0) { OggSoundFilePtr oggSoundFile = OggSoundFilePtr(new OggSoundFile(file)); if(oggSoundFile->prepareOgg()) soundFile = oggSoundFile; } else logError("unknown sound file format ", filename); return soundFile; }
void Map::saveOtcm(const std::string& fileName) { #if 0 try { g_clock.update(); FileStreamPtr fin = g_resources.createFile(fileName); fin->cache(); //TODO: compression flag with zlib uint32 flags = 0; // header fin->addU32(OTCM_SIGNATURE); fin->addU16(0); // data start, will be overwritten later fin->addU16(OTCM_VERSION); fin->addU32(flags); // version 1 header fin->addString("OTCM 1.0"); // map description fin->addU32(g_things.getDatSignature()); fin->addU16(g_game.getClientVersion()); fin->addString(g_game.getWorldName()); // go back and rewrite where the map data starts uint32 start = fin->tell(); fin->seek(4); fin->addU16(start); fin->seek(start); for(auto& pair : m_tiles) { const TilePtr& tile = pair.second; if(!tile || tile->isEmpty()) continue; Position pos = pair.first; fin->addU16(pos.x); fin->addU16(pos.y); fin->addU8(pos.z); const auto& list = tile->getThings(); auto first = std::find_if(list.begin(), list.end(), [](const ThingPtr& thing) { return thing->isItem(); }); for(auto it = first, end = list.end(); it != end; ++it) { const ThingPtr& thing = *it; if(thing->isItem()) { ItemPtr item = thing->static_self_cast<Item>(); fin->addU16(item->getId()); fin->addU8(item->getCountOrSubType()); } } // end of tile fin->addU16(0xFFFF); } // end of file Position invalidPos; fin->addU16(invalidPos.x); fin->addU16(invalidPos.y); fin->addU8(invalidPos.z); fin->flush(); fin->close(); } catch(stdext::exception& e) { g_logger.error(stdext::format("failed to save OTCM map: %s", e.what())); } #endif }
bool Map::loadOtcm(const std::string& fileName) { try { FileStreamPtr fin = g_resources.openFile(fileName); if(!fin) stdext::throw_exception("unable to open file"); stdext::timer loadTimer; fin->cache(); uint32 signature = fin->getU32(); if(signature != OTCM_SIGNATURE) stdext::throw_exception("invalid otcm file"); uint16 start = fin->getU16(); uint16 version = fin->getU16(); fin->getU32(); // flags switch(version) { case 1: { fin->getString(); // description uint32 datSignature = fin->getU32(); fin->getU16(); // protocol version fin->getString(); // world name if(datSignature != g_things.getDatSignature()) g_logger.warning("otcm map loaded was created with a different dat signature"); break; } default: stdext::throw_exception("otcm version not supported"); } fin->seek(start); while(true) { Position pos; pos.x = fin->getU16(); pos.y = fin->getU16(); pos.z = fin->getU8(); // end of file if(!pos.isValid()) break; const TilePtr& tile = g_map.createTile(pos); int stackPos = 0; while(true) { int id = fin->getU16(); // end of tile if(id == 0xFFFF) break; int countOrSubType = fin->getU8(); ItemPtr item = Item::create(id); item->setCountOrSubType(countOrSubType); if(item->isValid()) tile->addThing(item, stackPos++); } } fin->close(); g_logger.debug(stdext::format("Otcm load time: %.2f seconds", loadTimer.elapsed_seconds())); return true; } catch(stdext::exception& e) { g_logger.error(stdext::format("failed to load OTCM map: %s", e.what())); return false; } }
void Map::saveOtcm(const std::string& fileName) { try { stdext::timer saveTimer; FileStreamPtr fin = g_resources.createFile(fileName); fin->cache(); //TODO: compression flag with zlib uint32 flags = 0; // header fin->addU32(OTCM_SIGNATURE); fin->addU16(0); // data start, will be overwritten later fin->addU16(OTCM_VERSION); fin->addU32(flags); // version 1 header fin->addString("OTCM 1.0"); // map description fin->addU32(g_things.getDatSignature()); fin->addU16(g_game.getProtocolVersion()); fin->addString(g_game.getWorldName()); // go back and rewrite where the map data starts uint32 start = fin->tell(); fin->seek(4); fin->addU16(start); fin->seek(start); for(uint8_t z = 0; z <= Otc::MAX_Z; ++z) { for(const auto& it : m_tileBlocks[z]) { const TileBlock& block = it.second; for(const TilePtr& tile : block.getTiles()) { if(!tile || tile->isEmpty()) continue; Position pos = tile->getPosition(); fin->addU16(pos.x); fin->addU16(pos.y); fin->addU8(pos.z); for(const ThingPtr& thing : tile->getThings()) { if(thing->isItem()) { ItemPtr item = thing->static_self_cast<Item>(); fin->addU16(item->getId()); fin->addU8(item->getCountOrSubType()); } } // end of tile fin->addU16(0xFFFF); } } } // end of file Position invalidPos; fin->addU16(invalidPos.x); fin->addU16(invalidPos.y); fin->addU8(invalidPos.z); fin->flush(); fin->close(); } catch(stdext::exception& e) { g_logger.error(stdext::format("failed to save OTCM map: %s", e.what())); } }