Postado Dezembro 17, 2015 9 anos Salvar Mapa in-game! Informações Nome: Salvar mapa in-game! Versão: 1.0 Código: capaverde Testado em: theforgottenserver 0.2rc9 Descrição Toda vez que você abrir o executável de seu servidor, ele mudará automatica o ip no config.lua. Para isso ele usa o arquivo getip.js, que funciona como um detector que diz qual ip da máquina! Como usa isso? Só colocar saveMap() em algum script, mas olha que vai lagar. Dá pra facilmente criar um npc que salva o mapa de x em x horas, e se você for reiniciar o server por algum motivo é só kickar todo mundo e usar uma talkaction que salve. Tutorial luascript.h, procure por: static int32_t luaSaveMap(lua_State* L); luascript.cpp, dentro de registerFunctions(): //saveMap() lua_register(m_luaState, "saveMap", LuaScriptInterface::luaSaveMap); luascript.cpp: int32_t LuaScriptInterface::luaSaveMap(lua_State* L) { //saveMap() g_game.saveMapzord(); } game.h(public): void saveMapzord(){map->saveMapzord();} map.h, embaixo de bool saveMap();: bool saveMapzord(); map.cpp: bool Map::saveMapzord() { IOMap* loader = new IOMap(); bool saved = false; for(uint32_t tries = 0; tries < 3; tries++) { if(loader->saveMap(this, "eai.otbm", false)) { saved = true; break; } } return saved; } iomap.h: bool saveMap(Map* map, const std::string& identifier, bool showdialog); iomap.cpp: Spoiler bool IOMap::saveMap(Map* map, const std::string& identifier, bool showdialog) { /* STOP! * Before you even think about modifying this, please reconsider. * while adding stuff to the binary format may be "cool", you'll * inevitably make it incompatible with any future releases of * the map editor, meaning you cannot reuse your map. Before you * try to modify this, PLEASE consider using an external file * like spawns.xml or houses.xml, as that will be MUCH easier * to port to newer versions of the editor than a custom binary * format. */ /*if(Items::dwMajorVersion < 3) { version = 0; } else { version = 1; }*/ FileLoader f; f.openFile(identifier.c_str(), true, false); f.startNode(0); { f.addU32(0); // Version f.addU16((uint16_t)map->mapWidth); f.addU16((uint16_t)map->mapHeight); f.addU32(Items::dwMajorVersion); f.addU32(Items::dwMinorVersion); f.startNode(OTBM_MAP_DATA); { f.addByte(OTBM_ATTR_DESCRIPTION); // Neither SimOne's nor OpenTibia cares for additional description tags f.addString("Saved with Remere's Map Editor "); f.addU8(OTBM_ATTR_DESCRIPTION); f.addString("Esse mapa é maneiro."); /*f.addU8(OTBM_ATTR_EXT_SPAWN_FILE); FileName fn(wxstr(map->spawnfile)); f.addString(std::string((const char*)fn.GetFullName().mb_str(wxConvUTF8))); if(gui.GetCurrentVersion() > CLIENT_VERSION_760) { f.addU8(OTBM_ATTR_EXT_HOUSE_FILE); fn.Assign(wxstr(map->housefile)); f.addString(std::string((const char*)fn.GetFullName().mb_str(wxConvUTF8))); }*/ // Start writing tiles //uint64_t tiles_saved = 0; bool first = true; int local_x = -1, local_y = -1, local_z = -1; for (uint64_t z=0; z<=15; ++z) for (uint64_t xi = 0; xi<map->mapWidth; xi+=256) for (uint64_t yi = 0; yi<map->mapHeight; yi+=256) for (uint64_t x = xi; x<xi+256; x++) for (uint64_t y = yi; y<yi+256; y++){ //MapIterator map_iterator = map.begin(); //while(map_iterator != map.end()) { // Update progressbar //++tiles_saved; //if(showdialog && tiles_saved % 8192 == 0) { //gui.SetLoadDone(int(tiles_saved / double(map.getTileCount()) * 100.0)); //} // Get tile Tile* save_tile = map->getTile(x,y,z); //Tile* save_tile = *map_iterator; if (!save_tile) continue; const Position& pos = save_tile->getPosition(); /*// Is it an empty tile that we can skip? (Leftovers...) if(save_tile->size() == 0) { ++map_iterator; continue; }*/ // Decide if new node should be created if(pos.x < local_x || pos.x >= local_x + 256 || pos.y < local_y || pos.y >= local_y + 256 || pos.z != local_z) { // End last node if(!first) { f.endNode(); } first = false; // Start new node f.startNode(OTBM_TILE_AREA); f.addU16(local_x = pos.x & 0xFF00); f.addU16(local_y = pos.y & 0xFF00); f.addU8( local_z = pos.z); } //HouseTile* houseTile = dynamic_cast<HouseTile*>(save_tile); f.startNode(/*houseTile? OTBM_HOUSETILE : */OTBM_TILE); f.addU8(pos.x & 0xFF); f.addU8(pos.y & 0xFF); /*if(houseTile) { f.addU32(houseTile->getHouse()->getHouseId()); }*/ /*if(save_tile->getMapFlags()) { f.addByte(OTBM_ATTR_TILE_FLAGS); f.addU32(save_tile->getMapFlags()); }*/ if(save_tile->ground) { Item* ground = save_tile->ground; /*if(ground->hasBorderEquivalent()) { bool found = false; for(ItemVector::iterator it = save_tile->items.begin(); it != save_tile->items.end(); ++it) { if((*it)->getGroundEquivalent() == ground->getID()) { // Do nothing // Found equivalent found = true; break; } } if(found == false) { ground->serializeItemNode_OTBM(*this, f); } } else*/ if(ground->isComplex()) { ground->serializeItemNode_OTBM(f); } else { f.addByte(OTBM_ATTR_ITEM); ground->serializeItemCompact_OTBM(f); } } for(ItemVector::reverse_iterator it = save_tile->downItems.rbegin(); it != save_tile->downItems.rend(); ++it) { //if(!(*it)->isMetaItem()) { (*it)->serializeItemNode_OTBM(f); //} } for(ItemVector::iterator it = save_tile->topItems.begin(); it != save_tile->topItems.end(); ++it) { //if(!(*it)->isMetaItem()) { (*it)->serializeItemNode_OTBM(f); //} } f.endNode(); //++map_iterator; } // Only close the last node if one has actually been created if(!first) { f.endNode(); } f.startNode(OTBM_TOWNS); { //for(TownMap::const_iterator it = townMap.begin(); it != townMap.end(); ++it) { for(TownMap::const_iterator it = Towns::getInstance().getFirstTown(); it != Towns::getInstance().getLastTown(); ++it){ Town* town = it->second; f.startNode(OTBM_TOWN); f.addU32(town->getTownID()); f.addString(town->getName()); f.addU16(town->getTemplePosition().x); f.addU16(town->getTemplePosition().y); f.addU8 (town->getTemplePosition().z); f.endNode(); } } f.endNode(); } f.endNode(); //std::cout << tiles_saved << std::endl; } f.endNode(); /*if(showdialog) gui.SetLoadDone(100, wxT("Saving spawns...")); saveSpawns(map, identifier); if(gui.GetCurrentVersion() > CLIENT_VERSION_760) { if(showdialog) gui.SetLoadDone(100, wxT("Saving houses...")); saveHouses(map, identifier); }*/ return true; } item.h, public da class Item: //map-saving virtual bool serializeItemNode_OTBM(FileLoader& f) const; // Will write this item to the stream supplied in the argument virtual void serializeItemCompact_OTBM(FileLoader& f) const; virtual void serializeItemAttributes_OTBM(FileLoader& f) const; item.h, public da class ItemAttributes: virtual bool isComplex() const {return (15 & m_attributes) != 0;} item.cpp: Spoiler bool Item::serializeItemNode_OTBM(FileLoader& f) const { f.startNode(OTBM_ITEM); f.addU16(id); //if(maphandle.version == 0) { /*const ItemType& iType = items[id]; if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){ f.addU8(getSubType()); }*/ //} serializeItemAttributes_OTBM(f); f.endNode(); return true; } void Item::serializeItemAttributes_OTBM(FileLoader& stream) const { //if(maphandle.version > 0) { const ItemType& iType = items[id]; if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){ //stream.addU8(OTBM_ATTR_COUNT); stream.addU8(getItemCountOrSubtype()); } //}*/ /* if(items.dwMinorVersion >= CLIENT_VERSION_820 && isCharged()) { stream.addU8(OTBM_ATTR_CHARGES); stream.addU16(getSubtype()); }*/ if(getActionId()) { stream.addU8(OTBM_ATTR_ACTION_ID); stream.addU16(getActionId()); } if(getUniqueId()) { stream.addU8(OTBM_ATTR_UNIQUE_ID); stream.addU16(getUniqueId()); } if(getText().length() > 0) { stream.addU8(OTBM_ATTR_TEXT); stream.addString(getText()); } if(getSpecialDescription().length() > 0) { stream.addU8(OTBM_ATTR_DESC); stream.addString(getSpecialDescription()); } } void Item::serializeItemCompact_OTBM(FileLoader& stream) const { stream.addU16(id); /* This is impossible const ItemType& iType = item_db[id]; if(iType.stackable || iType.isSplash() || iType.isFluidContainer()){ stream.addU8(getSubtype()); } */ } fileloader.cpp: troque as funções addU8 e addU16 por essas (ou o mapa gerado vai tá corrompido): bool FileLoader::addU8(uint8_t u8) { writeData(&u8, sizeof(u8), true); //unescape=true, or else some FEsomething itemid might be recognized as the start of a node return m_lastError == ERROR_NONE; } bool FileLoader::addU16(uint16_t u16) { writeData(reinterpret_cast<uint8_t*>(&u16), sizeof(u16), true); return m_lastError == ERROR_NONE; }
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.