From c8f2916bdc60f7c5b632655cfe9bddaad3a15bc0 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Tue, 18 Oct 2011 00:13:34 +0200 Subject: Took interpreting the objects out of the map reader The map reader is now only concerned with parsing the XML, whereas the MapComposite turns some of the objects into Warps, Spawns and NPCs. Reviewed-by: Yohann Ferreira --- src/game-server/accountconnection.cpp | 15 ++- src/game-server/map.h | 3 + src/game-server/mapcomposite.cpp | 207 +++++++++++++++++++++++++++++----- src/game-server/mapcomposite.h | 27 ++--- src/game-server/mapmanager.cpp | 21 ++-- src/game-server/mapmanager.h | 3 +- src/game-server/mapreader.cpp | 156 ++----------------------- src/game-server/mapreader.h | 13 +-- 8 files changed, 229 insertions(+), 216 deletions(-) (limited to 'src') diff --git a/src/game-server/accountconnection.cpp b/src/game-server/accountconnection.cpp index 927b5c1..a6dc552 100644 --- a/src/game-server/accountconnection.cpp +++ b/src/game-server/accountconnection.cpp @@ -159,7 +159,7 @@ void AccountConnection::processMessage(MessageIn &msg) case AGMSG_ACTIVE_MAP: { int id = msg.readInt16(); - if (MapManager::raiseActive(id)) + if (MapManager::activateMap(id)) { // set map variables MapComposite *m = MapManager::getMap(id); @@ -260,7 +260,8 @@ void AccountConnection::playerReconnectAccount(int id, send(msg); } -void AccountConnection::requestCharacterVar(Character *ch, const std::string &name) +void AccountConnection::requestCharacterVar(Character *ch, + const std::string &name) { MessageOut msg(GAMSG_GET_VAR_CHR); msg.writeInt32(ch->getDatabaseID()); @@ -268,8 +269,9 @@ void AccountConnection::requestCharacterVar(Character *ch, const std::string &na send(msg); } -void AccountConnection::updateCharacterVar(Character *ch, const std::string &name, - const std::string &value) +void AccountConnection::updateCharacterVar(Character *ch, + const std::string &name, + const std::string &value) { MessageOut msg(GAMSG_SET_VAR_CHR); msg.writeInt32(ch->getDatabaseID()); @@ -278,8 +280,9 @@ void AccountConnection::updateCharacterVar(Character *ch, const std::string &nam send(msg); } -void AccountConnection::updateMapVar(MapComposite *map, const std::string &name, - const std::string &value) +void AccountConnection::updateMapVar(MapComposite *map, + const std::string &name, + const std::string &value) { MessageOut msg(GAMSG_SET_VAR_MAP); msg.writeInt32(map->getID()); diff --git a/src/game-server/map.h b/src/game-server/map.h index f1180a7..eca3686 100644 --- a/src/game-server/map.h +++ b/src/game-server/map.h @@ -92,6 +92,9 @@ class MapObject const Rectangle &getBounds() const { return mBounds; } + int getX() const { return mBounds.x; } + int getY() const { return mBounds.y; } + private: Rectangle mBounds; std::string mName; diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index d3475f7..ecd3956 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2006-2010 The Mana World Development Team + * Copyright (C) 2010-2011 The Mana Development Team * * This file is part of The Mana Server. * @@ -21,11 +22,17 @@ #include #include -#include "common/configuration.h" #include "accountconnection.h" -#include "game-server/map.h" -#include "game-server/mapcomposite.h" +#include "common/configuration.h" +#include "common/resourcemanager.h" #include "game-server/character.h" +#include "game-server/mapcomposite.h" +#include "game-server/map.h" +#include "game-server/mapmanager.h" +#include "game-server/mapreader.h" +#include "game-server/monstermanager.h" +#include "game-server/spawnarea.h" +#include "game-server/trigger.h" #include "scripting/script.h" #include "utils/logger.h" #include "utils/point.h" @@ -261,6 +268,11 @@ void ActorIterator::operator++() } } + +/****************************************************************************** + * ObjectBucket + *****************************************************************************/ + ObjectBucket::ObjectBucket() : free(256), next_object(0) { @@ -326,6 +338,11 @@ void ObjectBucket::deallocate(int i) ++free; } + +/****************************************************************************** + * MapContent + *****************************************************************************/ + MapContent::MapContent(Map *map) : last_bucket(0), zones(NULL) { @@ -433,6 +450,11 @@ MapZone& MapContent::getZone(const Point &pos) const return zones[(pos.x / zoneDiam) + (pos.y / zoneDiam) * mapWidth]; } + +/****************************************************************************** + * MapComposite + *****************************************************************************/ + MapComposite::MapComposite(int id, const std::string &name): mMap(NULL), mContent(NULL), @@ -449,6 +471,39 @@ MapComposite::~MapComposite() delete mScript; } +bool MapComposite::activate() +{ + assert(!isActive()); + + std::string file = "maps/" + mName + ".tmx"; + if (!ResourceManager::exists(file)) + file += ".gz"; + + mMap = MapReader::readMap(file); + if (!mMap) + return false; + + initializeContent(); + + std::string sPvP = mMap->getProperty("pvp"); + if (sPvP.empty()) + sPvP = Configuration::getValue("game_defaultPvp", std::string()); + + if (sPvP == "free") + mPvPRules = PVP_FREE; + else + mPvPRules = PVP_NONE; + + if (Script *s = getScript()) + { + s->setMap(this); + s->prepare("initialize"); + s->execute(); + } + + return true; +} + ZoneIterator MapComposite::getAroundPointIterator(const Point &p, int radius) const { MapRegion r; @@ -544,22 +599,6 @@ void MapComposite::remove(Thing *ptr) } } -void MapComposite::setMap(Map *m) -{ - assert(!mMap && m); - mMap = m; - mContent = new MapContent(m); - - std::string sPvP = m->getProperty("pvp"); - if (sPvP.empty()) - sPvP = Configuration::getValue("game_defaultPvp", std::string()); - - if (sPvP == "free") - mPvPRules = PVP_FREE; - else - mPvPRules = PVP_NONE; -} - void MapComposite::update() { for (int i = 0; i < mContent->mapHeight * mContent->mapWidth; ++i) @@ -596,12 +635,11 @@ const std::vector< Thing * > &MapComposite::getEverything() const } -std::string MapComposite::getVariable(const std::string &key) +std::string MapComposite::getVariable(const std::string &key) const { - std::map::iterator iValue = - mScriptVariables.find(key); - if (iValue != mScriptVariables.end()) - return iValue->second; + std::map::const_iterator i = mScriptVariables.find(key); + if (i != mScriptVariables.end()) + return i->second; else return std::string(); } @@ -609,9 +647,8 @@ std::string MapComposite::getVariable(const std::string &key) void MapComposite::setVariable(const std::string &key, const std::string &value) { // check if the value actually changed - std::map::iterator iOldValue = - mScriptVariables.find(key); - if (iOldValue == mScriptVariables.end() || iOldValue->second != value) + std::map::iterator i = mScriptVariables.find(key); + if (i == mScriptVariables.end() || i->second != value) { // changed value or unknown variable mScriptVariables[key] = value; @@ -619,3 +656,119 @@ void MapComposite::setVariable(const std::string &key, const std::string &value) accountHandler->updateMapVar(this, key, value); } } + +/** + * Initializes the map content. This creates the warps, spawn areas, npcs and + * other scripts. + */ +void MapComposite::initializeContent() +{ + mContent = new MapContent(mMap); + + const std::vector &objects = mMap->getObjects(); + + for (size_t i = 0; i < objects.size(); ++i) + { + const MapObject *object = objects.at(i); + const std::string &type = object->getType(); + + if (utils::compareStrI(type, "WARP") == 0) + { + std::string destMapName = object->getProperty("DEST_MAP"); + int destX = utils::stringToInt(object->getProperty("DEST_X")); + int destY = utils::stringToInt(object->getProperty("DEST_Y")); + + if (!destMapName.empty() && destX && destY) + { + if (MapComposite *destMap = MapManager::getMap(destMapName)) + { + WarpAction *action = new WarpAction(destMap, destX, destY); + insert(new TriggerArea(this, object->getBounds(), + action, false)); + } + } + else + { + LOG_WARN("Unrecognized warp format"); + } + } + else if (utils::compareStrI(type, "SPAWN") == 0) + { + MonsterClass *monster = 0; + int maxBeings = utils::stringToInt(object->getProperty("MAX_BEINGS")); + int spawnRate = utils::stringToInt(object->getProperty("SPAWN_RATE")); + std::string monsterName = object->getProperty("MONSTER_ID"); + int monsterId = utils::stringToInt(monsterName); + + if (monsterId) + { + monster = monsterManager->getMonster(monsterId); + if (!monster) + { + LOG_WARN("Couldn't find monster ID " << monsterId << + " for spawn area"); + } + } + else + { + monster = monsterManager->getMonsterByName(monsterName); + if (!monster) + { + LOG_WARN("Couldn't find monster " << monsterName << + " for spawn area"); + } + } + + if (monster && maxBeings && spawnRate) + { + insert(new SpawnArea(this, monster, object->getBounds(), + maxBeings, spawnRate)); + } + } + else if (utils::compareStrI(type, "NPC") == 0) + { + if (!mScript) + { + mScript = Script::create("lua"); + } + + int npcId = utils::stringToInt(object->getProperty("NPC_ID")); + std::string scriptText = object->getProperty("SCRIPT"); + + if (npcId && !scriptText.empty()) + { + mScript->loadNPC(object->getName(), npcId, + object->getX(), object->getY(), + scriptText.c_str()); + } + else + { + LOG_WARN("Unrecognized format for npc"); + } + } + else if (utils::compareStrI(type, "SCRIPT") == 0) + { + if (!mScript) + { + mScript = Script::create("lua"); + } + + std::string scriptFilename = object->getProperty("FILENAME"); + std::string scriptText = object->getProperty("TEXT"); + + if (!scriptFilename.empty()) + { + mScript->loadFile(scriptFilename); + } + else if (!scriptText.empty()) + { + std::string name = "'" + object->getName() + "'' in " + mName; + mScript->load(scriptText.c_str(), name.c_str()); + } + else + { + LOG_WARN("Unrecognized format for script"); + } + } + } +} diff --git a/src/game-server/mapcomposite.h b/src/game-server/mapcomposite.h index f34ad24..988b0ed 100644 --- a/src/game-server/mapcomposite.h +++ b/src/game-server/mapcomposite.h @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2006-2010 The Mana World Development Team + * Copyright (C) 2010-2011 The Mana Development Team * * This file is part of The Mana Server. * @@ -233,10 +234,13 @@ class MapComposite ~MapComposite(); /** - * Sets the underlying pathfinding map. - * Can be done only once. + * Loads the map and initializes the map content. Should only be called + * once! + * + * @return true when succesful, false when + * an error occurred. */ - void setMap(Map *); + bool activate(); /** * Gets the underlying pathfinding map. @@ -245,13 +249,8 @@ class MapComposite { return mMap; } /** - * Sets the associated script. - */ - void setScript(Script *s) - { mScript = s; } - - /** - * Gets the associated script. + * Gets the associated script. Returns 0 when no scripts or inline + * NPCs are used on this map! */ Script *getScript() const { return mScript; } @@ -329,13 +328,13 @@ class MapComposite /** * Gets the cached value of a map-bound script variable */ - std::string getVariable(const std::string &key); + std::string getVariable(const std::string &key) const; /** * Changes a script variable and notifies the database server * about the change */ - void setVariable (const std::string &key, const std::string &value); + void setVariable(const std::string &key, const std::string &value); /** * Changes a script variable without notifying the database server @@ -348,13 +347,15 @@ class MapComposite private: MapComposite(const MapComposite &); + void initializeContent(); + Map *mMap; /**< Actual map. */ MapContent *mContent; /**< Entities on the map. */ Script *mScript; /**< Script associated to this map. */ std::string mName; /**< Name of the map. */ unsigned short mID; /**< ID of the map. */ /** Cached persistent variables */ - std::map< std::string, std::string > mScriptVariables; + std::map mScriptVariables; PvPRules mPvPRules; }; diff --git a/src/game-server/mapmanager.cpp b/src/game-server/mapmanager.cpp index 094af92..4d7b25b 100644 --- a/src/game-server/mapmanager.cpp +++ b/src/game-server/mapmanager.cpp @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2004-2010 The Mana World Development Team + * Copyright (C) 2010-2011 The Mana Development Team * * This file is part of The Mana Server. * @@ -23,7 +24,6 @@ #include "common/resourcemanager.h" #include "game-server/map.h" #include "game-server/mapcomposite.h" -#include "game-server/mapreader.h" #include "utils/logger.h" #include "utils/xml.h" @@ -127,30 +127,25 @@ MapComposite *MapManager::getMap(const std::string &mapName) return NULL; } -bool MapManager::raiseActive(int mapId) +bool MapManager::activateMap(int mapId) { Maps::iterator i = maps.find(mapId); assert(i != maps.end()); MapComposite *composite = i->second; + if (composite->isActive()) - { return true; - } - std::string file = "maps/" + composite->getName() + ".tmx"; - if (!ResourceManager::exists(file)) - { - file += ".gz"; - } - if (MapReader::readMap(file, composite)) + if (composite->activate()) { - LOG_INFO("Activated map \"" << file << "\" (id " << mapId << ")"); + LOG_INFO("Activated map \"" << composite->getName() + << "\" (id " << mapId << ")"); return true; } else { - LOG_WARN("Couldn't activate invalid map \"" << file << "\" (id " << - mapId << ")"); + LOG_WARN("Couldn't activate invalid map \"" << composite->getName() + << "\" (id " << mapId << ")"); return false; } } diff --git a/src/game-server/mapmanager.h b/src/game-server/mapmanager.h index d21bd41..6b51881 100644 --- a/src/game-server/mapmanager.h +++ b/src/game-server/mapmanager.h @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2004-2010 The Mana World Development Team + * Copyright (C) 2010-2011 The Mana Development Team * * This file is part of The Mana Server. * @@ -62,7 +63,7 @@ namespace MapManager * Sets the activity status of the map. * @return true if the activation was successful. */ - bool raiseActive(int mapId); + bool activateMap(int mapId); } #endif // MAPMANAGER_H diff --git a/src/game-server/mapreader.cpp b/src/game-server/mapreader.cpp index e82fa10..87101a6 100644 --- a/src/game-server/mapreader.cpp +++ b/src/game-server/mapreader.cpp @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2004-2010 The Mana World Development Team + * Copyright (C) 2010-2011 The Mana Development Team * * This file is part of The Mana Server. * @@ -20,13 +21,8 @@ #include "game-server/mapreader.h" +#include "common/defines.h" #include "game-server/map.h" -#include "game-server/mapcomposite.h" -#include "game-server/mapmanager.h" -#include "game-server/monstermanager.h" -#include "game-server/spawnarea.h" -#include "game-server/trigger.h" -#include "scripting/script.h" #include "utils/base64.h" #include "utils/logger.h" #include "utils/xml.h" @@ -37,7 +33,7 @@ static std::vector< int > tilesetFirstGids; -bool MapReader::readMap(const std::string &filename, MapComposite *composite) +Map *MapReader::readMap(const std::string &filename) { XML::Document doc(filename); xmlNodePtr rootNode = doc.rootNode(); @@ -49,39 +45,16 @@ bool MapReader::readMap(const std::string &filename, MapComposite *composite) return false; } - std::vector things; - Map *map = readMap(rootNode, filename, composite, things); - - if (map) - { - composite->setMap(map); - - for (std::vector< Thing * >::const_iterator i = things.begin(), - i_end = things.end(); i != i_end; ++i) - { - composite->insert(*i); - } - - if (Script *s = composite->getScript()) - { - s->setMap(composite); - s->prepare("initialize"); - s->execute(); - } - } - return true; + return readMap(rootNode); } -Map* MapReader::readMap(xmlNodePtr node, const std::string &path, - MapComposite *composite, std::vector &things) +Map *MapReader::readMap(xmlNodePtr node) { - // Take the filename off the path - std::string pathDir = path.substr(0, path.rfind("/") + 1); int w = XML::getProperty(node, "width", 0); int h = XML::getProperty(node, "height", 0); - int tilew = XML::getProperty(node, "tilewidth", DEFAULT_TILE_LENGTH); - int tileh = XML::getProperty(node, "tileheight", DEFAULT_TILE_LENGTH); - Map* map = new Map(w, h, tilew, tileh); + int tileW = XML::getProperty(node, "tilewidth", DEFAULT_TILE_LENGTH); + int tileH = XML::getProperty(node, "tileheight", DEFAULT_TILE_LENGTH); + Map *map = new Map(w, h, tileW, tileH); for (node = node->xmlChildrenNode; node != NULL; node = node->next) { @@ -163,119 +136,6 @@ Map* MapReader::readMap(xmlNodePtr node, const std::string &path, } } - if (utils::compareStrI(objType, "WARP") == 0) - { - std::string destMapName = newObject->getProperty("DEST_MAP"); - int destX = utils::stringToInt( - newObject->getProperty("DEST_X")); - int destY = utils::stringToInt( - newObject->getProperty("DEST_Y")); - - if (!destMapName.empty() && destX && destY) - { - MapComposite *destMap = MapManager::getMap(destMapName); - if (destMap) - { - things.push_back(new TriggerArea( - composite, rect, - new WarpAction(destMap, destX, destY), false)); - } - } - else - { - LOG_WARN("Unrecognized warp format"); - } - } - else if (utils::compareStrI(objType, "SPAWN") == 0) - { - MonsterClass *monster = 0; - int maxBeings = utils::stringToInt( - newObject->getProperty("MAX_BEINGS")); - int spawnRate = utils::stringToInt( - newObject->getProperty("SPAWN_RATE")); - std::string monsterName = - newObject->getProperty("MONSTER_ID"); - int monsterId = utils::stringToInt(monsterName); - if (monsterId) - { - monster = monsterManager->getMonster( - monsterId); - if (!monster) - { - LOG_WARN("Couldn't find monster ID " - << monsterId << - " for spawn area"); - } - } - else - { - monster = monsterManager-> - getMonsterByName(monsterName); - if (!monster) - { - LOG_WARN("Couldn't find monster " - << monsterName << - " for spawn area"); - } - } - if (monster && maxBeings && spawnRate) - { - things.push_back(new SpawnArea(composite, monster, rect, - maxBeings, spawnRate)); - } - } - else if (utils::compareStrI(objType, "NPC") == 0) - { - Script *s = composite->getScript(); - if (!s) - { - // Create a Lua context. - s = Script::create("lua"); - composite->setScript(s); - } - - int npcId = utils::stringToInt( - newObject->getProperty("NPC_ID")); - std::string scriptText = newObject->getProperty("SCRIPT"); - - if (npcId && !scriptText.empty()) - { - s->loadNPC(objName, npcId, objX, objY, scriptText.c_str()); - } - else - { - LOG_WARN("Unrecognized format for npc"); - } - } - else if (utils::compareStrI(objType, "SCRIPT") == 0) - { - Script *s = composite->getScript(); - if (!s) - { - // Create a Lua context. - s = Script::create("lua"); - composite->setScript(s); - } - - std::string scriptFilename = - newObject->getProperty("FILENAME"); - std::string scriptText = newObject->getProperty("TEXT"); - - if (!scriptFilename.empty()) - { - s->loadFile(scriptFilename); - } - else if (!scriptText.empty()) - { - const std::string name = "'" + objName + "'' in " + path; - s->load(scriptText.c_str(), name.c_str()); - } - else - { - LOG_WARN("Unrecognized format for script"); - } - } - map->addObject(newObject); } } diff --git a/src/game-server/mapreader.h b/src/game-server/mapreader.h index f4a0e5f..725737f 100644 --- a/src/game-server/mapreader.h +++ b/src/game-server/mapreader.h @@ -1,6 +1,7 @@ /* * The Mana Server * Copyright (C) 2004-2010 The Mana World Development Team + * Copyright (C) 2010-2011 The Mana Development Team * * This file is part of The Mana Server. * @@ -38,19 +39,15 @@ class MapReader public: /** * Read an XML map from a file. - * @return true if it was successful. + * @return the map when successful, 0 otherwise. */ - static bool readMap(const std::string &filename, - MapComposite *composite); + static Map *readMap(const std::string &filename); private: /** - * Read an XML map from a parsed XML tree, and populate things with - * objects in that map. + * Read an XML map from a parsed XML tree. */ - static Map *readMap(xmlNodePtr node, const std::string &path, - MapComposite *composite, - std::vector &things); + static Map *readMap(xmlNodePtr node); /** * Reads a map layer and adds it to the given map. -- cgit