/* * 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. * * The Mana Server is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * The Mana Server is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with The Mana Server. If not, see . */ #ifndef SERVER_MAPCOMPOSITE_H #define SERVER_MAPCOMPOSITE_H #include #include #include #include "scripting/script.h" class Actor; class Being; class Character; class Map; class MapComposite; class Point; class Rectangle; class Thing; struct MapContent; struct MapZone; enum PvPRules { PVP_NONE, // no PvP on this map PVP_FREE // unrestricted PvP on this map // [space for additional PvP modes] }; /** * Ordered sets of zones of a map. */ typedef std::vector< unsigned > MapRegion; /** * Iterates through the zones of a region of the map. */ struct ZoneIterator { MapRegion region; /**< Zones to visit. Empty means the entire map. */ unsigned pos; MapZone *current; const MapContent *map; ZoneIterator(const MapRegion &, const MapContent *); void operator++(); MapZone *operator*() const { return current; } operator bool() const { return current; } }; /** * Iterates through the Characters of a region. */ struct CharacterIterator { ZoneIterator iterator; unsigned short pos; Character *current; CharacterIterator(const ZoneIterator &); void operator++(); Character *operator*() const { return current; } operator bool() const { return iterator; } }; /** * Iterates through the Beings of a region. */ struct BeingIterator { ZoneIterator iterator; unsigned short pos; Being *current; BeingIterator(const ZoneIterator &); void operator++(); Being *operator*() const { return current; } operator bool() const { return iterator; } }; /** * Iterates through the non-moving Actors of a region. */ struct FixedActorIterator { ZoneIterator iterator; unsigned short pos; Actor *current; FixedActorIterator(const ZoneIterator &); void operator++(); Actor *operator*() const { return current; } operator bool() const { return iterator; } }; /** * Iterates through the Actors of a region. */ struct ActorIterator { ZoneIterator iterator; unsigned short pos; Actor *current; ActorIterator(const ZoneIterator &); void operator++(); Actor *operator*() const { return current; } operator bool() const { return iterator; } }; /** * Part of a map. */ struct MapZone { unsigned short nbCharacters, nbMovingObjects; /** * Objects present in this zone. * Characters are stored first, then the remaining MovingObjects, then the * remaining Objects. */ std::vector< Actor * > objects; /** * Destinations of the objects that left this zone. * This is necessary in order to have an accurate iterator around moving * objects. */ MapRegion destinations; MapZone(): nbCharacters(0), nbMovingObjects(0) {} void insert(Actor *); void remove(Actor *); }; /** * Pool of public IDs for MovingObjects on a map. By maintaining public ID * availability using bits, it can locate an available public ID fast while * using minimal memory access. */ struct ObjectBucket { static int const int_bitsize = sizeof(unsigned) * 8; unsigned bitmap[256 / int_bitsize]; /**< Bitmap of free locations. */ short free; /**< Number of empty places. */ short next_object; /**< Next object to look at. */ Actor *objects[256]; ObjectBucket(); int allocate(); void deallocate(int); }; /** * Entities on a map. */ struct MapContent { MapContent(Map *); ~MapContent(); /** * Allocates a unique ID for an actor on this map. */ bool allocate(Actor *); /** * Deallocates an ID. */ void deallocate(Actor *); /** * Fills a region of zones within the range of a point. */ void fillRegion(MapRegion &, const Point &, int) const; /** * Fills a region of zones inside a rectangle. */ void fillRegion(MapRegion &, const Rectangle &) const; /** * Gets zone at given position. */ MapZone &getZone(const Point &pos) const; /** * Things (items, characters, monsters, etc) located on the map. */ std::vector< Thing * > things; /** * Buckets of MovingObjects located on the map, referenced by ID. */ ObjectBucket *buckets[256]; int last_bucket; /**< Last bucket acted upon. */ /** * Partition of the Objects, depending on their position on the map. */ MapZone *zones; unsigned short mapWidth; /**< Width with respect to zones. */ unsigned short mapHeight; /**< Height with respect to zones. */ }; /** * Combined map/entity structure. */ class MapComposite { public: MapComposite(int id, const std::string &name); ~MapComposite(); /** * Loads the map and initializes the map content. Should only be called * once! * * @return true when succesful, false when * an error occurred. */ bool activate(); /** * Gets the underlying pathfinding map. */ Map *getMap() const { return mMap; } /** * Returns whether the map is active on this server or not. */ bool isActive() const { return mMap; } /** * Gets the game ID of this map. */ int getID() const { return mID; } /** * Gets the name of this map. */ const std::string &getName() const { return mName; } /** * Inserts a thing on the map. Sets its public ID if relevant. */ bool insert(Thing *); /** * Removes a thing from the map. */ void remove(Thing *); /** * Updates zones of every moving beings. */ void update(); /** * Gets the PvP rules on the map. */ PvPRules getPvP() const { return mPvPRules; } /** * Gets an iterator on the objects of the whole map. */ ZoneIterator getWholeMapIterator() const { return ZoneIterator(MapRegion(), mContent); } /** * Gets an iterator on the objects inside a given rectangle. */ ZoneIterator getInsideRectangleIterator(const Rectangle &) const; /** * Gets an iterator on the objects around a given point. */ ZoneIterator getAroundPointIterator(const Point &, int radius) const; /** * Gets an iterator on the objects around a given actor. */ ZoneIterator getAroundActorIterator(Actor *, int radius) const; /** * Gets an iterator on the objects around the old and new positions of * a character (including the ones that were but are now elsewhere). */ ZoneIterator getAroundBeingIterator(Being *, int radius) const; /** * Gets everything related to the map. */ const std::vector< Thing * > &getEverything() const; /** * Gets the cached value of a map-bound script variable */ 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); /** * Changes a script variable without notifying the database server * about the change */ void setVariableFromDbserver (const std::string &key, const std::string &value) { mScriptVariables[key] = value; } static void setInitializeCallback(Script *script) { script->assignCallback(mInitializeCallback); } private: MapComposite(const MapComposite &); void initializeContent(); Map *mMap; /**< Actual map. */ MapContent *mContent; /**< Entities on the map. */ std::string mName; /**< Name of the map. */ unsigned short mID; /**< ID of the map. */ /** Cached persistent variables */ std::map mScriptVariables; PvPRules mPvPRules; static Script::Ref mInitializeCallback; }; #endif