#include "world.h" #include #include #include "frame.h" #include World::World() { newMap(); rootChildren.push_back(0); } World::World(std::string filename) { this->filename = filename; xmlDocPtr doc = xmlParseFile(filename.c_str()); if (doc == nullptr) { throw MapLoadException(filename); } xmlNodePtr top = xmlDocGetRootElement(doc); if (top == nullptr) { throw MapLoadException(filename); } if (xmlStrcmp(top->name, (const xmlChar*) "world")) { throw MapLoadException(filename); } for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) { if (!xmlStrcmp(node->name, (const xmlChar*) "nextmapid")) { xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if (key != 0) { nextMapID = atoi((char*) key); } xmlFree(key); } else if (!xmlStrcmp(node->name, (const xmlChar*) "lastmap")) { xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if (key != 0) { lastmap = atoi((char*) key); } xmlFree(key); } else if (!xmlStrcmp(node->name, (const xmlChar*) "root")) { xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); if (key != 0) { rootChildren.push_back(atoi((char*) key)); } xmlFree(key); } else if (!xmlStrcmp(node->name, (const xmlChar*) "map")) { xmlChar* idKey = xmlGetProp(node, (xmlChar*) "id"); if (idKey == 0) throw MapLoadException(filename); int id = atoi((char*) idKey); xmlFree(idKey); auto map = std::make_shared(id, this); for (xmlNodePtr mapNode = node->xmlChildrenNode; mapNode != NULL; mapNode = mapNode->next) { if (!xmlStrcmp(mapNode->name, (const xmlChar*) "name")) { xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); if (key != 0) { map->setTitle((char*) key, false); } xmlFree(key); } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "environment")) { xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); int* mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int)); mapdata[0] = atoi(strtok((char*) key, ",\n")); for (int i=1; i<(MAP_WIDTH*MAP_HEIGHT); i++) { mapdata[i] = atoi(strtok(NULL, ",\n")); } map->setMapdata(mapdata, false); xmlFree(key); } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "leftmap")) { xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); if (key != 0) { map->setLeftmap(atoi((char*) key), false); } xmlFree(key); } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "rightmap")) { xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); if (key != 0) { map->setRightmap(atoi((char*) key)); } xmlFree(key); } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "entities")) { for (xmlNodePtr entityNode = mapNode->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next) { if (!xmlStrcmp(entityNode->name, (const xmlChar*) "entity")) { auto data = std::make_shared(); for (xmlNodePtr entityDataNode = entityNode->xmlChildrenNode; entityDataNode != NULL; entityDataNode = entityDataNode->next) { if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-type")) { xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1); data->object = MapObject::getAllObjects().at((char*) key).get(); xmlFree(key); } else if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-position")) { xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1); sscanf((char*) key, "%lf,%lf", &data->position.first, &data->position.second); xmlFree(key); } } map->addObject(data, false); } } } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "child")) { xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); if (key != 0) { map->addChild(atoi((char*) key)); } xmlFree(key); } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "expanded")) { xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); if ((key != 0) && ((char) key[0] == '1')) { map->setExpanded(true); } } } maps[map->getID()] = map; } } xmlFreeDoc(doc); } std::shared_ptr World::newMap() { auto nm = std::make_shared(nextMapID++, this); maps[nm->getID()] = nm; return nm; } std::shared_ptr World::getMap(int id) const { return maps.at(id); } void World::setDirty(bool dirty) { this->dirty = dirty; parent->MapDirtyDidChange(dirty); } bool World::getDirty() const { return dirty; } std::string World::getFilename() const { return filename; } void World::setParent(MapeditFrame* parent) { this->parent = parent; } Map* World::getLastMap() const { return getMap(lastmap).get(); } #define MY_ENCODING "ISO-8859-1" void World::save(std::string name, wxTreeCtrl* mapTree) { int rc; xmlTextWriterPtr writer = xmlNewTextWriterFilename(name.c_str(), 0); if (writer == NULL) throw MapWriteException(name); rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL); if (rc < 0) throw MapWriteException(name); // rc = xmlTextWriterStartElement(writer, (xmlChar*) "world"); if (rc < 0) throw MapWriteException(name); // std::ostringstream nextMap_out; nextMap_out << nextMapID; rc = xmlTextWriterWriteElement(writer, (xmlChar*) "nextmapid", (xmlChar*) nextMap_out.str().c_str()); if (rc < 0) throw MapWriteException(name); // std::ostringstream lastMap_out; lastMap_out << lastmap; rc = xmlTextWriterWriteElement(writer, (xmlChar*) "lastmap", (xmlChar*) lastMap_out.str().c_str()); if (rc < 0) throw MapWriteException(name); // ASSUMPTION: There will always be at least one child of the invisible root element. i.e. you cannot delete to zero maps. wxTreeItemId root = mapTree->GetRootItem(); wxTreeItemIdValue cookie1; for (wxTreeItemId it = mapTree->GetFirstChild(root, cookie1); it.IsOk(); it = mapTree->GetNextChild(root, cookie1)) { // MapPtrCtr* ctl = (MapPtrCtr*) mapTree->GetItemData(it); std::ostringstream rootid_out; rootid_out << ctl->map->getID(); rc = xmlTextWriterWriteElement(writer, (xmlChar*) "root", (xmlChar*) rootid_out.str().c_str()); if (rc < 0) throw MapWriteException(name); } for (auto mapPair : maps) { Map& map = *mapPair.second; // rc = xmlTextWriterStartElement(writer, (xmlChar*) "map"); if (rc < 0) throw MapWriteException(name); // id= std::ostringstream id_out; id_out << map.getID(); rc = xmlTextWriterWriteAttribute(writer, (xmlChar*) "id", (xmlChar*) id_out.str().c_str()); if (rc < 0) throw MapWriteException(name); // rc = xmlTextWriterWriteElement(writer, (xmlChar*) "name", (xmlChar*) map.getTitle().c_str()); if (rc < 0) throw MapWriteException(name); // std::ostringstream mapdata_out; for (int y=0; y std::ostringstream leftmap_out; if (map.getLeftmap()) { leftmap_out << map.getLeftmap()->getID(); } rc = xmlTextWriterWriteElement(writer, (xmlChar*) "leftmap", (xmlChar*) leftmap_out.str().c_str()); if (rc < 0) throw MapWriteException(name); // std::ostringstream rightmap_out; if (map.getRightmap()) { rightmap_out << map.getRightmap()->getID(); } rc = xmlTextWriterWriteElement(writer, (xmlChar*) "rightmap", (xmlChar*) rightmap_out.str().c_str()); if (rc < 0) throw MapWriteException(name); // rc = xmlTextWriterStartElement(writer, (xmlChar*) "entities"); if (rc < 0) throw MapWriteException(name); for (auto object : map.getObjects()) { // rc = xmlTextWriterStartElement(writer, (xmlChar*) "entity"); if (rc < 0) throw MapWriteException(name); // rc = xmlTextWriterWriteElement(writer, (xmlChar*) "entity-type", (xmlChar*) object->object->getType().c_str()); if (rc < 0) throw MapWriteException(name); // std::ostringstream entpos_out; entpos_out << object->position.first << "," << object->position.second; rc = xmlTextWriterWriteElement(writer, (xmlChar*) "entity-position", (xmlChar*) entpos_out.str().c_str()); if (rc < 0) throw MapWriteException(name); // rc = xmlTextWriterEndElement(writer); if (rc < 0) throw MapWriteException(name); } // rc = xmlTextWriterEndElement(writer); if (rc < 0) throw MapWriteException(name); wxTreeItemId node = map.getTreeItemId(); if (mapTree->ItemHasChildren(node)) { wxTreeItemIdValue cookie2; for (wxTreeItemId it = mapTree->GetFirstChild(node, cookie2); it.IsOk(); it = mapTree->GetNextChild(node, cookie2)) { // MapPtrCtr* ctl = (MapPtrCtr*) mapTree->GetItemData(it); std::ostringstream childid_out; childid_out << ctl->map->getID(); rc = xmlTextWriterWriteElement(writer, (xmlChar*) "child", (xmlChar*) childid_out.str().c_str()); if (rc < 0) throw MapWriteException(name); } if (mapTree->IsExpanded(node)) { // rc = xmlTextWriterWriteElement(writer, (xmlChar*) "expanded", (xmlChar*) "1"); if (rc < 0) throw MapWriteException(name); } } // rc = xmlTextWriterEndElement(writer); if (rc < 0) throw MapWriteException(name); } // rc = xmlTextWriterEndDocument(writer); if (rc < 0) throw MapWriteException(name); xmlFreeTextWriter(writer); setDirty(false); } std::list> World::getRootMaps() const { std::list> ret; for (auto id : rootChildren) { ret.push_back(getMap(id)); } return ret; } const std::map> World::getMaps() const { return maps; }