Ir para conteúdo

Featured Replies

Postado

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;
}

 

  • 2 months later...
  • 1 year later...

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.

Visitante
Responder

Quem Está Navegando 0

  • Nenhum usuário registrado visualizando esta página.

Estatísticas dos Fóruns

  • Tópicos 96.9k
  • Posts 519.6k

Informação Importante

Confirmação de Termo