示例#1
0
bool GraphicManager::loadOTFI(const FileName& filename, wxString& error, wxArrayString& warnings)
{
	otfi_found = wxFileExists(filename.GetFullPath());
	if(otfi_found) {
		std::string path = std::string(filename.GetFullPath().mb_str());
		OTMLDocumentPtr doc = OTMLDocument::parse(path);

		if(doc->size() == 0 || !doc->hasChildAt("DatSpr")) {
			error += "'DatSpr' tag not found";
			return false;
		}

		OTMLNodePtr node = doc->get("DatSpr");
		is_extended = node->valueAt<bool>("extended");
		has_transparency = node->valueAt<bool>("transparency");
		has_frame_durations = node->valueAt<bool>("frame-durations");
		has_frame_groups = node->valueAt<bool>("frame-groups");
	} else {
		is_extended = false;
		has_transparency = false;
		has_frame_durations = false;
		has_frame_groups = false;
	}
	return true;
}
示例#2
0
bool IOMapOTMM::saveMap(Map& map, const FileName& identifier, bool showdialog) {
	DiskNodeFileWriteHandle f(std::string(identifier.GetFullPath().mb_str(wxConvUTF8)));
	
	if(f.isOk() == false){
		error(wxT("Can not open file %s for writing"), (const char*)identifier.GetFullPath().mb_str(wxConvUTF8));
		return false;
	}

	if(showdialog) gui.CreateLoadBar(wxT("Saving OTMM map..."));
	bool ret = saveMap(map, f, identifier, showdialog);
	if(showdialog) gui.DestroyLoadBar();

	return ret;
}
示例#3
0
文件: creatures.cpp 项目: LaloHao/rme
bool CreatureDatabase::saveToXML(const FileName& filename)
{
	pugi::xml_document doc;
	
	pugi::xml_node decl = doc.prepend_child(pugi::node_declaration);
	decl.append_attribute("version") = "1.0";

	pugi::xml_node creatureNodes = doc.append_child("creatures");
	for (const auto& creatureEntry : creature_map) {
		CreatureType* creatureType = creatureEntry.second;
		if (!creatureType->standard) {
			pugi::xml_node creatureNode = creatureNodes.append_child("creature");

			creatureNode.append_attribute("name") = creatureType->name.c_str();
			creatureNode.append_attribute("type") = creatureType->isNpc ? "npc" : "monster";

			const Outfit& outfit = creatureType->outfit;
			creatureNode.append_attribute("looktype") = outfit.lookType;
			creatureNode.append_attribute("lookitem") = outfit.lookItem;
			creatureNode.append_attribute("lookaddon") = outfit.lookAddon;
			creatureNode.append_attribute("lookhead") = outfit.lookHead;
			creatureNode.append_attribute("lookbody") = outfit.lookBody;
			creatureNode.append_attribute("looklegs") = outfit.lookLegs;
			creatureNode.append_attribute("lookfeet") = outfit.lookFeet;
		}
	}
	return doc.save_file(filename.GetFullPath().mb_str(), "\t", pugi::format_default, pugi::encoding_utf8);
}
示例#4
0
文件: creatures.cpp 项目: LaloHao/rme
bool CreatureDatabase::loadFromXML(const FileName& filename, bool standard, wxString& error, wxArrayString& warnings)
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file(filename.GetFullPath().mb_str());
	if (!result) {
		error = wxT("Couldn't open file \"") + filename.GetFullName() + wxT("\", invalid format?");
		return false;
	}

	pugi::xml_node node = doc.child("creatures");
	if (!node) {
		error = wxT("Invalid file signature, this file is not a valid creatures file.");
		return false;
	}

	for (pugi::xml_node creatureNode = node.first_child(); creatureNode; creatureNode = creatureNode.next_sibling()) {
		if (as_lower_str(creatureNode.name()) != "creature") {
			continue;
		}

		CreatureType* creatureType = CreatureType::loadFromXML(creatureNode, warnings);
		if (creatureType) {
			creatureType->standard = standard;
			if ((*this)[creatureType->name]) {
				warnings.push_back(wxT("Duplicate creature type name \"") + wxstr(creatureType->name) + wxT("\"! Discarding..."));
				delete creatureType;
			} else {
				creature_map[as_lower_str(creatureType->name)] = creatureType;
			}
		}
	}
	return true;
}
示例#5
0
ClientVersionID IOMapOTMM::getVersionInfo(const FileName& filename)
{
	wxString wpath = filename.GetFullPath();
	DiskNodeFileReadHandle f((const char*)wpath.mb_str(wxConvUTF8));
	if(f.isOk() == false) {
		return CLIENT_VERSION_NONE;
	}

	BinaryNode* root = f.getRootNode();
	if(!root) {return CLIENT_VERSION_NONE;}
	root->skip(1); // Skip the type byte

	uint16_t u16;
	uint32_t u32;

	if(!root->getU32(u32) || u32 != 1) { // Version
		return CLIENT_VERSION_NONE;
	}

	root->getU16(u16);
	root->getU16(u16);
	root->getU32(u32);

	if(root->getU32(u32)) { // OTB minor version
		return ClientVersionID(u32);
	}
	return CLIENT_VERSION_NONE;
}
示例#6
0
bool IOMapOTMM::loadMap(Map& map, const FileName& identifier, bool showdialog) {
	if(showdialog) gui.CreateLoadBar(wxT("Loading OTMM map..."));
	DiskNodeFileReadHandle f(nstr(identifier.GetFullPath()));
	if(f.isOk() == false) {
		error(wxT("Couldn't open file for reading\nThe error reported was: ") + wxstr(f.getErrorMessage()));
		return false;
	}

	bool ret = loadMap(map, f, identifier, showdialog);

	if(showdialog) gui.DestroyLoadBar();

	return ret;
}
示例#7
0
文件: materials.cpp 项目: TheSumm/rme
bool Materials::loadMaterials(const FileName& identifier, wxString& error, wxArrayString& warnings)
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file(identifier.GetFullPath().mb_str());
	if(!result) {
		warnings.push_back("Could not open " + identifier.GetFullName() + " (file not found or syntax error)");
		return false;
	}

	pugi::xml_node node = doc.child("materials");
	if(!node) {
		warnings.push_back(identifier.GetFullName() + ": Invalid rootheader.");
		return false;
	}

	unserializeMaterials(identifier, node, error, warnings);
	return true;
}
示例#8
0
文件: items.cpp 项目: Codex-NG/rme
bool ItemDatabase::loadFromGameXml(const FileName& identifier, wxString& error, wxArrayString& warnings)
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file(identifier.GetFullPath().mb_str());
	if(!result) {
		error = wxT("Could not load items.xml (Syntax error?)");
		return false;
	}

	pugi::xml_node node = doc.child("items");
	if(!node) {
		error = wxT("items.xml, invalid root node.");
		return false;
	}

	for(pugi::xml_node itemNode = node.first_child(); itemNode; itemNode = itemNode.next_sibling()) {
		if(as_lower_str(itemNode.name()) != "item") {
			continue;
		}

		int32_t fromId = pugi::cast<int32_t>(itemNode.attribute("fromid").value());
		int32_t toId = pugi::cast<int32_t>(itemNode.attribute("toid").value());
		if(pugi::xml_attribute attribute = itemNode.attribute("id")) {
			fromId = toId = pugi::cast<int32_t>(attribute.value());
		}

		if(fromId == 0 || toId == 0) {
			error = wxT("Could not read item id from item node.");
			return false;
		}

		for(int32_t id = fromId; id <= toId; ++id) {
			if(!loadItemFromGameXml(itemNode, id)) {
				return false;
			}
		}
	}
	return true;
}
示例#9
0
bool Materials::loadMaterials(const FileName& identifier, wxString& error, wxArrayString& warnings)
{
	xmlDocPtr doc = xmlParseFile(identifier.GetFullPath().mb_str());
	if(doc)
	{
		xmlNodePtr root = xmlDocGetRootElement(doc);
		
		if(xmlStrcmp(root->name,(const xmlChar*)"materials") != 0)
		{
			xmlFreeDoc(doc);
			error = wxT("materials.xml: Invalid root header");
			return false;
		}

		unserializeMaterials(identifier, root, error, warnings);
	}
	else
	{
		error = wxT("Couldn't open materials.xml (file not found or syntax error)");
		return false;
	}
	return true;
}
示例#10
0
bool GraphicManager::loadSpriteData(const FileName& datafile, wxString& error, wxArrayString& warnings)
{
	FileReadHandle fh(nstr(datafile.GetFullPath()));

	if(!fh.isOk()) {
		error = "Failed to open file for reading";
		return false;
	}

#define safe_get(func, ...) do {\
		if(!fh.get##func(__VA_ARGS__)) {\
			error = wxstr(fh.getErrorMessage()); \
			return false; \
		} \
	} while(false)


	uint32_t sprSignature;
	safe_get(U32, sprSignature);

	uint32_t total_pics = 0;
	if(is_extended) {
		safe_get(U32, total_pics);
	} else {
		uint16_t u16 = 0;
		safe_get(U16, u16);
		total_pics = u16;
	}

	if(!g_settings.getInteger(Config::USE_MEMCACHED_SPRITES)) {
		spritefile = nstr(datafile.GetFullPath());
		unloaded = false;
		return true;
	}

	std::vector<uint32_t> sprite_indexes;
	for(uint32_t i = 0; i < total_pics; ++i) {
		uint32_t index;
		safe_get(U32, index);
		sprite_indexes.push_back(index);
	}

	// Now read individual sprites
	int id = 1;
	for(std::vector<uint32_t>::iterator sprite_iter = sprite_indexes.begin(); sprite_iter != sprite_indexes.end(); ++sprite_iter, ++id) {
		uint32_t index = *sprite_iter + 3;
		fh.seek(index);
		uint16_t size;
		safe_get(U16, size);

		ImageMap::iterator it = image_space.find(id);
		if(it != image_space.end()) {
			GameSprite::NormalImage* spr = dynamic_cast<GameSprite::NormalImage*>(it->second);
			if(spr && size > 0) {
				if(spr->size > 0) {
					wxString ss;
					ss << "items.spr: Duplicate GameSprite id " << id;
					warnings.push_back(ss);
					fh.seekRelative(size);
				} else {
					spr->id = id;
					spr->size = size;
					spr->dump = newd uint8_t[size];
					if(!fh.getRAW(spr->dump, size)) {
						error = wxstr(fh.getErrorMessage()); \
						return false;
					}
				}
			}
		} else {
			fh.seekRelative(size);
		}
	}
#undef safe_get
	unloaded = false;
	return true;
}
示例#11
0
bool GraphicManager::loadSpriteMetadata(const FileName& datafile, wxString& error, wxArrayString& warnings)
{
	// items.otb has most of the info we need. This only loads the GameSprite metadata
	FileReadHandle file(nstr(datafile.GetFullPath()));

	if(!file.isOk()) {
		error += "Failed to open " + datafile.GetFullPath() + " for reading\nThe error reported was:" + wxstr(file.getErrorMessage());
		return false;
	}

	uint16_t effect_count, distance_count;

	uint32_t datSignature;
	file.getU32(datSignature);
	//get max id
	file.getU16(item_count);
	file.getU16(creature_count);
	file.getU16(effect_count);
	file.getU16(distance_count);

	uint32_t minclientID = 100; // tibia.dat start with id 100
	// We don't load distance/effects, if we would, just add effect_count & distance_count here
	uint32_t maxclientID = item_count + creature_count;

	dat_format = client_version->getDatFormatForSignature(datSignature);

	if(!otfi_found) {
		is_extended = dat_format >= DAT_FORMAT_96;
		has_frame_durations = dat_format >= DAT_FORMAT_1050;
		has_frame_groups = dat_format >= DAT_FORMAT_1057;
	}

	uint16_t id = minclientID;
	// loop through all ItemDatabase until we reach the end of file
	while(id <= maxclientID) {
		GameSprite* sType = newd GameSprite();
		sprite_space[id] = sType;

		sType->id = id;

		// Load the sprite flags
		if(!loadSpriteMetadataFlags(file, sType, error, warnings)) {
			wxString msg;
			msg << "Failed to load flags for sprite " << sType->id;
			warnings.push_back(msg);
		}

		// Reads the group count
		uint8_t group_count = 1;
		if(has_frame_groups && id > item_count) {
			file.getU8(group_count);
		}

		for(uint32_t k = 0; k < group_count; ++k) {
			// Skipping the group type
			if(has_frame_groups && id > item_count) {
				file.skip(1);
			}

			// Size and GameSprite data
			file.getByte(sType->width);
			file.getByte(sType->height);

			// Skipping the exact size
			if((sType->width > 1) || (sType->height > 1)){
				file.skip(1);
			}

			file.getU8(sType->layers); // Number of blendframes (some sprites consist of several merged sprites)
			file.getU8(sType->pattern_x);
			file.getU8(sType->pattern_y);
			if(dat_format <= DAT_FORMAT_74)
				sType->pattern_z = 1;
			else
				file.getU8(sType->pattern_z);
			file.getU8(sType->frames); // Length of animation
			
			if(sType->frames > 1) {
				uint8_t async = 0;
				int loop_count = 0;
				int8_t start_frame = 0;
				if(has_frame_durations) {
					file.getByte(async);
					file.get32(loop_count);
					file.getSByte(start_frame);
				}
				sType->animator = newd Animator(sType->frames, start_frame, loop_count, async == 1);
				if(has_frame_durations) {
					for(int i = 0; i < sType->frames; i++) {
						uint32_t min;
						uint32_t max;
						file.getU32(min);
						file.getU32(max);
						FrameDuration* frame_duration = sType->animator->getFrameDuration(i);
						frame_duration->setValues(int(min), int(max));
					}
					sType->animator->reset();
				}
			}

			sType->numsprites =
				(int)sType->width * (int)sType->height *
				(int)sType->layers *
				(int)sType->pattern_x * (int)sType->pattern_y * sType->pattern_z *
				(int)sType->frames;

			// Read the sprite ids
			for(uint32_t i = 0; i < sType->numsprites; ++i) {
				uint32_t sprite_id;
				if(is_extended) {
					file.getU32(sprite_id);
				} else {
					uint16_t u16 = 0;
					file.getU16(u16);
					sprite_id = u16;
				}

				if(image_space[sprite_id] == nullptr) {
					GameSprite::NormalImage* img = newd GameSprite::NormalImage();
					img->id = sprite_id;
					image_space[sprite_id] = img;
				}
				sType->spriteList.push_back(static_cast<GameSprite::NormalImage*>(image_space[sprite_id]));
			}
		}
		++id;
	}

	return true;
}
示例#12
0
文件: creatures.cpp 项目: LaloHao/rme
bool CreatureDatabase::importXMLFromOT(const FileName& filename, wxString& error, wxArrayString& warnings)
{
	pugi::xml_document doc;
	pugi::xml_parse_result result = doc.load_file(filename.GetFullPath().mb_str());
	if (!result) {
		error = wxT("Couldn't open file \"") + filename.GetFullName() + wxT("\", invalid format?");
		return false;
	}

	pugi::xml_node node;
	if ((node = doc.child("monsters"))) {
		for (pugi::xml_node monsterNode = node.first_child(); monsterNode; monsterNode = monsterNode.next_sibling()) {
			if (as_lower_str(monsterNode.name()) != "monster") {
				continue;
			}

			pugi::xml_attribute attribute;
			if (!(attribute = monsterNode.attribute("file"))) {
				continue;
			}

			FileName monsterFile(filename);
			monsterFile.SetFullName(wxString(attribute.as_string(), wxConvUTF8));

			pugi::xml_document monsterDoc;
			pugi::xml_parse_result monsterResult = monsterDoc.load_file(monsterFile.GetFullPath().mb_str());
			if (!monsterResult) {
				continue;
			}

			CreatureType* creatureType = CreatureType::loadFromOTXML(monsterFile, monsterDoc, warnings);
			if (creatureType) {
				CreatureType* current = (*this)[creatureType->name];
				if (current) {
					*current = *creatureType;
					delete creatureType;
				} else {
					creature_map[as_lower_str(creatureType->name)] = creatureType;

					Tileset* tileSet = nullptr;
					if (creatureType->isNpc) {
						tileSet = materials.tilesets["NPCs"];
					} else {
						tileSet = materials.tilesets["Others"];
					}
					ASSERT(tileSet != nullptr);
					
					Brush* brush = newd CreatureBrush(creatureType);
					brushes.addBrush(brush);

					TilesetCategory* tileSetCategory = tileSet->getCategory(TILESET_CREATURE);
					tileSetCategory->brushlist.push_back(brush);
				}
			}
		}
	} else if ((node = doc.child("monster")) || (node = doc.child("npc"))) {
		CreatureType* creatureType = CreatureType::loadFromOTXML(filename, doc, warnings);
		if (creatureType) {
			CreatureType* current = (*this)[creatureType->name];

			if (current) {
				*current = *creatureType;
				delete creatureType;
			} else {
				creature_map[as_lower_str(creatureType->name)] = creatureType;

				Tileset* tileSet = nullptr;
				if (creatureType->isNpc) {
					tileSet = materials.tilesets["NPCs"];
				} else {
					tileSet = materials.tilesets["Others"];
				}
				ASSERT(tileSet != nullptr);

				Brush* brush = newd CreatureBrush(creatureType);
				brushes.addBrush(brush);

				TilesetCategory* tileSetCategory = tileSet->getCategory(TILESET_CREATURE);
				tileSetCategory->brushlist.push_back(brush);
			}
		}
	} else {
		error = wxT("This is not valid OT npc/monster data file.");
		return false;
	}
	return true;
}
示例#13
0
文件: materials.cpp 项目: TheSumm/rme
bool Materials::loadExtensions(FileName directoryName, wxString& error, wxArrayString& warnings)
{
	directoryName.Mkdir(0755, wxPATH_MKDIR_FULL); // Create if it doesn't exist

	wxDir ext_dir(directoryName.GetPath());
	if(!ext_dir.IsOpened()) {
		error = "Could not open extensions directory.";
		return false;
	}

	wxString filename;
	if(!ext_dir.GetFirst(&filename)) {
		// No extensions found
		return true;
	}

	StringVector clientVersions;
	do {
		FileName fn;
		fn.SetPath(directoryName.GetPath());
		fn.SetFullName(filename);
		if(fn.GetExt() != "xml") {
			continue;
		}

		pugi::xml_document doc;
		pugi::xml_parse_result result = doc.load_file(fn.GetFullPath().mb_str());
		if(!result) {
			warnings.push_back("Could not open " + filename + " (file not found or syntax error)");
			continue;
		}

		pugi::xml_node extensionNode = doc.child("materialsextension");
		if(!extensionNode) {
			warnings.push_back(filename + ": Invalid rootheader.");
			continue;
		}

		pugi::xml_attribute attribute;
		if(!(attribute = extensionNode.attribute("name"))) {
			warnings.push_back(filename + ": Couldn't read extension name.");
			continue;
		}

		const std::string& extensionName = attribute.as_string();
		if(!(attribute = extensionNode.attribute("author"))) {
			warnings.push_back(filename + ": Couldn't read extension name.");
			continue;
		}

		const std::string& extensionAuthor = attribute.as_string();
		if(!(attribute = extensionNode.attribute("description"))) {
			warnings.push_back(filename + ": Couldn't read extension name.");
			continue;
		}

		const std::string& extensionDescription = attribute.as_string();
		if(extensionName.empty() || extensionAuthor.empty() || extensionDescription.empty()) {
			warnings.push_back(filename + ": Couldn't read extension attributes (name, author, description).");
			continue;
		}

		std::string extensionUrl = extensionNode.attribute("url").as_string();
		extensionUrl.erase(std::remove(extensionUrl.begin(), extensionUrl.end(), '\''));

		std::string extensionAuthorLink = extensionNode.attribute("authorurl").as_string();
		extensionAuthorLink.erase(std::remove(extensionAuthorLink.begin(), extensionAuthorLink.end(), '\''));

		MaterialsExtension* materialExtension = newd MaterialsExtension(extensionName, extensionAuthor, extensionDescription);
		materialExtension->url = extensionUrl;
		materialExtension->author_url = extensionAuthorLink;

		if((attribute = extensionNode.attribute("client"))) {
			clientVersions.clear();
			const std::string& extensionClientString = attribute.as_string();

			size_t lastPosition = 0;
			size_t position = extensionClientString.find(';');
			while(position != std::string::npos) {
				clientVersions.push_back(extensionClientString.substr(lastPosition, position - lastPosition));
				lastPosition = position + 1;
				position = extensionClientString.find(';', lastPosition);
			}

			clientVersions.push_back(extensionClientString.substr(lastPosition));
			for(const std::string& version : clientVersions) {
				materialExtension->addVersion(version);
			}

			std::sort(materialExtension->version_list.begin(), materialExtension->version_list.end(), VersionComparisonPredicate);

			auto duplicate = std::unique(materialExtension->version_list.begin(), materialExtension->version_list.end());
			while(duplicate != materialExtension->version_list.end()) {
				materialExtension->version_list.erase(duplicate);
				duplicate = std::unique(materialExtension->version_list.begin(), materialExtension->version_list.end());
			}
		} else {
			warnings.push_back(filename + ": Extension is not available for any version.");
		}

		extensions.push_back(materialExtension);
		if(materialExtension->isForVersion(g_gui.GetCurrentVersionID())) {
			unserializeMaterials(filename, extensionNode, error, warnings);
		}
	} while(ext_dir.GetNext(&filename));

	return true;
}
示例#14
0
bool Materials::loadExtensions(FileName directoryName, wxString& error, wxArrayString& warnings)
{
	directoryName.Mkdir(0755, wxPATH_MKDIR_FULL); // Create if it doesn't exist

	wxDir ext_dir(directoryName.GetPath());
	if(ext_dir.IsOpened() == false)
	{
		error = wxT("Could not open extensions directory.");
		return false;
	}

	wxString filename;
	if(!ext_dir.GetFirst(&filename))
	{
		// No extensions found
		return true;
	}

	do
	{
		FileName fn;
		fn.SetPath(directoryName.GetPath());
		fn.SetFullName(filename);
		if(fn.GetExt() != wxT("xml"))
			continue;

		xmlDocPtr doc = xmlParseFile(fn.GetFullPath().mb_str());

		if(doc)
		{
			xmlNodePtr root = xmlDocGetRootElement(doc);
			
			if(xmlStrcmp(root->name,(const xmlChar*)"materialsextension") != 0){
				xmlFreeDoc(doc);
				warnings.push_back(filename + wxT(": Invalid rootheader."));
				continue;
			}
			std::string ext_name, ext_url, ext_author, ext_author_link, ext_desc, ext_client_str;
			StringVector clientVersions;
			if(
				!readXMLValue(root, "name", ext_name) ||
				!readXMLValue(root, "author", ext_author) ||
				!readXMLValue(root, "description", ext_desc))
			{
				warnings.push_back(filename + wxT(": Couldn't read extension attributes (name, author, description)."));
				continue;
			}


			readXMLValue(root, "url", ext_url);
			ext_url.erase(std::remove(ext_url.begin(), ext_url.end(), '\''), ext_url.end());
			readXMLValue(root, "authorurl", ext_author_link);
			ext_author_link.erase(std::remove(ext_author_link.begin(), ext_author_link.end(), '\''), ext_author_link.end());

			MaterialsExtension* me = newd MaterialsExtension(ext_name, ext_author, ext_desc);
			me->url = ext_url;
			me->author_url = ext_author_link;

			if(readXMLValue(root, "client", ext_client_str))
			{
				size_t last_pos = std::numeric_limits<size_t>::max();
				size_t pos;
				do
				{
					size_t to_pos = (last_pos == std::numeric_limits<size_t>::max()? 0 : last_pos+1);
					pos = ext_client_str.find(';', to_pos);
					if(size_t(pos) != std::string::npos)
					{
						clientVersions.push_back(ext_client_str.substr(to_pos, pos-(to_pos)));
						last_pos = pos;
					}
					else
					{
						clientVersions.push_back(ext_client_str.substr(to_pos));
						break;
					}
				} while(true);

				for(StringVector::iterator iter = clientVersions.begin();
						iter != clientVersions.end();
						++iter)
				{
					me->addVersion(*iter);
				}

				std::sort(me->version_list.begin(), me->version_list.end(), VersionComparisonPredicate);
				me->version_list.erase(std::unique(me->version_list.begin(), me->version_list.end()), me->version_list.end());
			}
			else
			{
				warnings.push_back(filename + wxT(": Extension is not available for any version."));
			}
			extensions.push_back(me);
			
			if(me->isForVersion(gui.GetCurrentVersionID()))
			{
				unserializeMaterials(filename, root, error, warnings);
			}
		}
		else
		{
			warnings.push_back(wxT("Could not open ") + filename + wxT(" (file not found or syntax error)"));
			continue;
		}
	} while(ext_dir.GetNext(&filename));

	return true;
}
示例#15
0
文件: map.cpp 项目: OMARTINEZ210/rme
bool Map::exportMinimap(FileName filename, int floor /*= 7*/, bool displaydialog)
{
	uint8_t* pic = nullptr;

	try
	{
		int min_x = 0x10000, min_y = 0x10000;
		int max_x = 0x00000, max_y = 0x00000;

		if(size() == 0)
			return true;

		for(MapIterator mit = begin(); mit != end(); ++mit) {
			if((*mit)->get() == nullptr || (*mit)->empty())
				continue;
			
			Position pos = (*mit)->getPosition();

			if(pos.x < min_x)
				min_x = pos.x;

			if(pos.y < min_y)
				min_y = pos.y;

			if(pos.x > max_x)
				max_x = pos.x;

			if(pos.y > max_y)
				max_y = pos.y;

		}

		int minimap_width = max_x - min_x+1;
		int minimap_height = max_y - min_y+1;

		pic = newd uint8_t[minimap_width*minimap_height]; // 1 byte per pixel
			
		memset(pic, 0, minimap_width*minimap_height);

		int tiles_iterated = 0;
		for(MapIterator mit = begin(); mit != end(); ++mit) {
			Tile* tile = (*mit)->get();
			++tiles_iterated;
			if(tiles_iterated % 8192 == 0 && displaydialog)
				gui.SetLoadDone(int(tiles_iterated / double(tilecount) * 90.0));
				
			if(tile->empty() || tile->getZ() != floor)
				continue;

			//std::cout << "Pixel : " << (tile->getY() - min_y) * width + (tile->getX() - min_x) << std::endl;
			uint32_t pixelpos = (tile->getY() - min_y) * minimap_width + (tile->getX() - min_x);
			uint8_t& pixel = pic[pixelpos];

			for(ItemVector::const_reverse_iterator item_iter = tile->items.rbegin(); item_iter != tile->items.rend(); ++item_iter) {
				if((*item_iter)->getMiniMapColor()) {
					pixel = (*item_iter)->getMiniMapColor();
					break;
				}
			}
			if(pixel == 0)
				// check ground too
				if(tile->hasGround())
					pixel = tile->ground->getMiniMapColor();
		}

		// Create a file for writing
		FileWriteHandle fh(nstr(filename.GetFullPath()));

		if(!fh.isOpen()) {
			delete[] pic;
			return false;
		}
		// Store the magic number
		fh.addRAW("BM");

		// Store the file size
		// We need to predict how large it will be
		uint32_t file_size =
					14 // header
					+40 // image data header
					+256*4 // color palette
					+((minimap_width + 3) / 4 * 4) * height; // pixels
		fh.addU32(file_size);

		// Two values reserved, must always be 0.
		fh.addU16(0);
		fh.addU16(0);

		// Bitmapdata offset
		fh.addU32(14 + 40 + 256*4);

		// Header size
		fh.addU32(40);

		// Header width/height
		fh.addU32(minimap_width);
		fh.addU32(minimap_height);

		// Color planes
		fh.addU16(1);

		// bits per pixel, OT map format is 8
		fh.addU16(8);

		// compression type, 0 is no compression
		fh.addU32(0);

		// image size, 0 is valid if we use no compression
		fh.addU32(0);

		// horizontal/vertical resolution in pixels / meter
		fh.addU32(4000);
		fh.addU32(4000);

		// Number of colors
		fh.addU32(256);
		// Important colors, 0 is all
		fh.addU32(0);

		// Write the color palette
		for(int i = 0; i < 256; ++i)
			fh.addU32(uint32_t(minimap_color[i]));

		// Bitmap width must be divisible by four, calculate how much padding we need
		int padding = ((minimap_width & 3) != 0? 4-(minimap_width & 3) : 0);
		// Bitmap rows are saved in reverse order
		for(int y = minimap_height-1; y >= 0; --y) {
			fh.addRAW(pic + y*minimap_width, minimap_width);
			for(int i = 0; i < padding; ++i) {
				fh.addU8(0);
			}
			if(y % 100 == 0 && displaydialog) {
				gui.SetLoadDone(90 + int((minimap_height-y) / double(minimap_height) * 10.0));
			}
		}

		delete[] pic;
		//fclose(file);
		fh.close();
	}
	catch(...)
	{
		delete[] pic;
	}

	return true;
}