1 // ============================================================== 2 // This file is part of Glest (www.glest.org) 3 // 4 // Copyright (C) 2001-2008 Martiño Figueroa 5 // 6 // You can redistribute this code and/or modify it under 7 // the terms of the GNU General Public License as published 8 // by the Free Software Foundation; either version 2 of the 9 // License, or (at your option) any later version 10 // ============================================================== 11 12 #ifndef _GLEST_GAME_FACTION_H_ 13 #define _GLEST_GAME_FACTION_H_ 14 15 #ifdef WIN32 16 #include <winsock2.h> 17 #include <winsock.h> 18 #endif 19 20 #include <vector> 21 #include <map> 22 #include "upgrade.h" 23 #include "texture.h" 24 #include "resource.h" 25 #include "game_constants.h" 26 #include "command_type.h" 27 #include "base_thread.h" 28 #include <set> 29 #include "faction_type.h" 30 #include "leak_dumper.h" 31 32 using std::map; 33 using std::vector; 34 using std::set; 35 36 using Shared::Graphics::Texture2D; 37 using namespace Shared::PlatformCommon; 38 39 namespace Glest{ namespace Game{ 40 41 class Unit; 42 class TechTree; 43 class FactionType; 44 class ProducibleType; 45 class RequirableType; 46 class CommandType; 47 class UnitType; 48 class Game; 49 class ScriptManager; 50 class World; 51 class Faction; 52 class GameSettings; 53 class SurfaceCell; 54 55 class FowAlphaCellsLookupItem { 56 public: 57 58 std::map<Vec2i,float> surfPosAlphaList; 59 }; 60 61 class ExploredCellsLookupItem { 62 public: 63 ExploredCellsLookupItem()64 ExploredCellsLookupItem() { 65 ExploredCellsLookupItemCacheTimerCountIndex = 0; 66 } 67 int ExploredCellsLookupItemCacheTimerCountIndex; 68 std::vector<SurfaceCell *> exploredCellList; 69 std::vector<SurfaceCell *> visibleCellList; 70 71 static time_t lastDebug; 72 }; 73 74 // ===================================================== 75 // class Faction 76 // 77 /// Each of the game players 78 // ===================================================== 79 80 struct CommandGroupUnitSorter { 81 bool operator()(const Unit *l, const Unit *r); 82 bool compare(const Unit *l, const Unit *r); 83 }; 84 85 struct CommandGroupUnitSorterId { 86 Faction *faction; 87 bool operator()(const int l, const int r); 88 }; 89 90 class FactionThread : public BaseThread, public SlaveThreadControllerInterface { 91 protected: 92 93 Faction *faction; 94 Semaphore semTaskSignalled; 95 Mutex *triggerIdMutex; 96 std::pair<int,bool> frameIndex; 97 MasterSlaveThreadController *masterController; 98 99 virtual void setQuitStatus(bool value); 100 virtual void setTaskCompleted(int frameIndex); 101 virtual bool canShutdown(bool deleteSelfIfShutdownDelayed=false); 102 103 public: 104 FactionThread(Faction *faction); 105 virtual ~FactionThread(); 106 virtual void execute(); 107 setMasterController(MasterSlaveThreadController * master)108 virtual void setMasterController(MasterSlaveThreadController *master) { masterController = master; } signalSlave(void * userdata)109 virtual void signalSlave(void *userdata) { signalPathfinder(*((int *)(userdata))); } 110 111 void signalPathfinder(int frameIndex); 112 bool isSignalPathfinderCompleted(int frameIndex); 113 }; 114 115 class SwitchTeamVote { 116 public: 117 118 int factionIndex; 119 int oldTeam; 120 int newTeam; 121 bool voted; 122 bool allowSwitchTeam; 123 }; 124 125 class Faction { 126 private: 127 typedef vector<Resource> Resources; 128 typedef vector<Resource> Store; 129 typedef vector<Faction*> Allies; 130 typedef vector<Unit*> Units; 131 typedef map<int, Unit*> UnitMap; 132 133 private: 134 UpgradeManager upgradeManager; 135 136 Resources resources; 137 Store store; 138 Allies allies; 139 140 Mutex *unitsMutex; 141 Units units; 142 UnitMap unitMap; 143 World *world; 144 ScriptManager *scriptManager; 145 146 FactionPersonalityType overridePersonalityType; 147 ControlType control; 148 149 Texture2D *texture; 150 FactionType *factionType; 151 152 int index; 153 int teamIndex; 154 int startLocationIndex; 155 156 bool thisFaction; 157 158 bool factionDisconnectHandled; 159 160 bool cachingDisabled; 161 std::map<Vec2i,int> cacheResourceTargetList; 162 std::map<Vec2i,bool> cachedCloseResourceTargetLookupList; 163 164 RandomGen random; 165 FactionThread *workerThread; 166 167 std::map<int,SwitchTeamVote> switchTeamVotes; 168 int currentSwitchTeamVoteFactionIndex; 169 170 bool allowSharedTeamUnits; 171 set<int> livingUnits; 172 set<Unit*> livingUnitsp; 173 174 std::map<int,int> unitsMovingList; 175 std::map<int,int> unitsPathfindingList; 176 177 std::set<const UnitType*> lockedUnits; 178 179 TechTree *techTree; 180 const XmlNode *loadWorldNode; 181 182 std::vector<string> worldSynchThreadedLogList; 183 184 std::map<int,string> crcWorldFrameDetails; 185 186 std::map<int,const Unit *> aliveUnitListCache; 187 std::map<int,const Unit *> mobileUnitListCache; 188 std::map<int,const Unit *> beingBuiltUnitListCache; 189 190 std::map<std::string, bool> resourceTypeCostCache; 191 192 public: 193 Faction(); 194 ~Faction(); 195 Faction(const Faction & obj)196 Faction(const Faction& obj) { 197 init(); 198 throw megaglest_runtime_error("class Faction is NOT safe to copy!"); 199 } 200 Faction & operator=(const Faction& obj) { 201 init(); 202 throw megaglest_runtime_error("class Faction is NOT safe to assign!"); 203 } 204 205 void notifyUnitAliveStatusChange(const Unit *unit); 206 void notifyUnitTypeChange(const Unit *unit, const UnitType *newType); 207 void notifyUnitSkillTypeChange(const Unit *unit, const SkillType *newType); 208 bool hasAliveUnits(bool filterMobileUnits, bool filterBuiltUnits) const; 209 addWorldSynchThreadedLogList(const string & data)210 inline void addWorldSynchThreadedLogList(const string &data) { 211 if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { 212 worldSynchThreadedLogList.push_back(data); 213 } 214 } clearWorldSynchThreadedLogList()215 inline void clearWorldSynchThreadedLogList() { 216 if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { 217 worldSynchThreadedLogList.clear(); 218 } 219 } dumpWorldSynchThreadedLogList()220 inline void dumpWorldSynchThreadedLogList() { 221 if(SystemFlags::getSystemSettingType(SystemFlags::debugWorldSynch).enabled == true) { 222 if(worldSynchThreadedLogList.empty() == false) { 223 for(unsigned int index = 0; index < worldSynchThreadedLogList.size(); ++index) { 224 SystemFlags::OutputDebug(SystemFlags::debugWorldSynch,worldSynchThreadedLogList[index].c_str()); 225 } 226 worldSynchThreadedLogList.clear(); 227 } 228 } 229 } 230 addLivingUnits(int id)231 inline void addLivingUnits(int id) { livingUnits.insert(id); } addLivingUnitsp(Unit * unit)232 inline void addLivingUnitsp(Unit *unit) { livingUnitsp.insert(unit); } 233 isUnitInLivingUnitsp(Unit * unit)234 inline bool isUnitInLivingUnitsp(Unit *unit) { return (livingUnitsp.find(unit) != livingUnitsp.end()); } deleteLivingUnits(int id)235 inline void deleteLivingUnits(int id) { livingUnits.erase(id); } deleteLivingUnitsp(Unit * unit)236 inline void deleteLivingUnitsp(Unit *unit) { livingUnitsp.erase(unit); } 237 238 //std::map<int,int> unitsMovingList; 239 void addUnitToMovingList(int unitId); 240 void removeUnitFromMovingList(int unitId); 241 int getUnitMovingListCount(); 242 243 void addUnitToPathfindingList(int unitId); 244 void removeUnitFromPathfindingList(int unitId); 245 int getUnitPathfindingListCount(); 246 void clearUnitsPathfinding(); 247 bool canUnitsPathfind(); 248 249 void setLockedUnitForFaction(const UnitType *ut, bool lock); isUnitLocked(const UnitType * ut)250 bool isUnitLocked(const UnitType *ut) const { return lockedUnits.find(ut)!=lockedUnits.end(); } 251 252 void init( 253 FactionType *factionType, ControlType control, TechTree *techTree, Game *game, 254 int factionIndex, int teamIndex, int startLocationIndex, bool thisFaction, 255 bool giveResources, const XmlNode *loadWorldNode=NULL); 256 void end(); 257 getFactionDisconnectHandled()258 inline bool getFactionDisconnectHandled() const { return factionDisconnectHandled;} setFactionDisconnectHandled(bool value)259 void setFactionDisconnectHandled(bool value) { factionDisconnectHandled=value;} 260 261 //get 262 const Resource *getResource(const ResourceType *rt,bool localFactionOnly=false) const; getResource(int i)263 inline const Resource *getResource(int i) const {return &resources[i];} 264 int getStoreAmount(const ResourceType *rt,bool localFactionOnly=false) const; getType()265 inline const FactionType *getType() const {return factionType;} getIndex()266 inline int getIndex() const {return index;} 267 getTeam()268 inline int getTeam() const {return teamIndex;} setTeam(int team)269 void setTeam(int team) {teamIndex=team;} 270 getTechTree()271 inline TechTree * getTechTree() const { return techTree; } 272 const SwitchTeamVote * getFirstSwitchTeamVote() const; 273 SwitchTeamVote * getSwitchTeamVote(int factionIndex); 274 void setSwitchTeamVote(SwitchTeamVote &vote); getCurrentSwitchTeamVoteFactionIndex()275 inline int getCurrentSwitchTeamVoteFactionIndex() const { return currentSwitchTeamVoteFactionIndex; } setCurrentSwitchTeamVoteFactionIndex(int index)276 void setCurrentSwitchTeamVoteFactionIndex(int index) { currentSwitchTeamVoteFactionIndex = index; } 277 278 bool getCpuControl(bool enableServerControlledAI, bool isNetworkGame, NetworkRole role) const; 279 bool getCpuControl() const; getCpuEasyControl()280 inline bool getCpuEasyControl() const {return control==ctCpuEasy;} getCpuUltraControl()281 inline bool getCpuUltraControl() const {return control==ctCpuUltra;} getCpuMegaControl()282 inline bool getCpuMegaControl() const {return control==ctCpuMega;} getControlType()283 inline ControlType getControlType() const {return control;} 284 285 FactionPersonalityType getPersonalityType() const; setPersonalityType(FactionPersonalityType pType)286 void setPersonalityType(FactionPersonalityType pType) { overridePersonalityType=pType; } 287 int getAIBehaviorStaticOverideValue(AIBehaviorStaticValueCategory type) const; 288 getUnit(int i)289 inline Unit *getUnit(int i) const { 290 Unit *result = units[i]; 291 return result; 292 } getUnitCount()293 inline int getUnitCount() const { 294 int result = (int)units.size(); 295 return result; 296 } getUnitMutex()297 inline Mutex * getUnitMutex() {return unitsMutex;} 298 getUpgradeManager()299 inline const UpgradeManager *getUpgradeManager() const {return &upgradeManager;} getTexture()300 inline const Texture2D *getTexture() const {return texture;} getStartLocationIndex()301 inline int getStartLocationIndex() const {return startLocationIndex;} getThisFaction()302 inline bool getThisFaction() const {return thisFaction;} 303 304 //upgrades 305 void startUpgrade(const UpgradeType *ut); 306 void cancelUpgrade(const UpgradeType *ut); 307 void finishUpgrade(const UpgradeType *ut); 308 309 //cost application 310 bool applyCosts(const ProducibleType *p,const CommandType *ct); 311 void applyDiscount(const ProducibleType *p, int discount); 312 void applyStaticCosts(const ProducibleType *p,const CommandType *ct); 313 void applyStaticProduction(const ProducibleType *p,const CommandType *ct); 314 void deApplyCosts(const ProducibleType *p,const CommandType *ct); 315 void deApplyStaticCosts(const ProducibleType *p,const CommandType *ct); 316 void deApplyStaticConsumption(const ProducibleType *p,const CommandType *ct); 317 void applyCostsOnInterval(const ResourceType *rtApply); 318 bool checkCosts(const ProducibleType *pt,const CommandType *ct); 319 320 //reqs 321 bool reqsOk(const RequirableType *rt) const; 322 bool reqsOk(const CommandType *ct) const; 323 int getCountForMaxUnitCount(const UnitType *unitType) const; 324 325 //diplomacy 326 bool isAlly(const Faction *faction); 327 328 //other 329 Unit *findUnit(int id) const; 330 void addUnit(Unit *unit); 331 void removeUnit(Unit *unit); 332 void addStore(const UnitType *unitType); 333 void removeStore(const UnitType *unitType); 334 335 //resources 336 void incResourceAmount(const ResourceType *rt, int amount); 337 void setResourceBalance(const ResourceType *rt, int balance); 338 setControlType(ControlType value)339 void setControlType(ControlType value) { control = value; } 340 341 bool isResourceTargetInCache(const Vec2i &pos,bool incrementUseCounter=false); 342 void addResourceTargetToCache(const Vec2i &pos,bool incrementUseCounter=true); 343 void removeResourceTargetFromCache(const Vec2i &pos); 344 void addCloseResourceTargetToCache(const Vec2i &pos); 345 Vec2i getClosestResourceTypeTargetFromCache(Unit *unit, const ResourceType *type,int frameIndex); 346 Vec2i getClosestResourceTypeTargetFromCache(const Vec2i &pos, const ResourceType *type); 347 void cleanupResourceTypeTargetCache(std::vector<Vec2i> *deleteListPtr,int frameIndex); getCacheResourceTargetListSize()348 inline int getCacheResourceTargetListSize() const { return (int)cacheResourceTargetList.size(); } 349 350 Unit * findClosestUnitWithSkillClass(const Vec2i &pos,const CommandClass &cmdClass, 351 const std::vector<SkillClass> &skillClassList, 352 const UnitType *unitType); 353 354 void deletePixels(); 355 getWorld()356 inline World * getWorld() { return world; } 357 int getFrameCount(); 358 359 void signalWorkerThread(int frameIndex); 360 bool isWorkerThreadSignalCompleted(int frameIndex); getWorkerThread()361 FactionThread *getWorkerThread() { return workerThread; } 362 363 void limitResourcesToStore(); 364 365 void sortUnitsByCommandGroups(); 366 367 bool canCreateUnit(const UnitType *ut, bool checkBuild, bool checkProduce, bool checkMorph) const; 368 369 string getCacheStats(); 370 uint64 getCacheKBytes(uint64 *cache1Size, uint64 *cache2Size, uint64 *cache3Size, uint64 *cache4Size, uint64 *cache5Size); 371 372 std::string toString(bool crcMode=false) const; 373 374 void saveGame(XmlNode *rootNode); 375 void loadGame(const XmlNode *rootNode, int factionIndex,GameSettings *settings,World *world); 376 377 void clearCaches(); 378 379 Checksum getCRC(); 380 void addCRC_DetailsForWorldFrame(int worldFrameCount,bool isNetworkServer); 381 string getCRC_DetailsForWorldFrame(int worldFrameCount); 382 std::pair<int,string> getCRC_DetailsForWorldFrameIndex(int worldFrameIndex) const; 383 string getCRC_DetailsForWorldFrames() const; 384 uint64 getCRC_DetailsForWorldFrameCount() const; 385 386 void updateUnitTypeWithResourceCostCache(const ResourceType *rt); 387 bool hasUnitTypeWithResourceCostInCache(const ResourceType *rt) const; 388 389 private: 390 void init(); 391 void resetResourceAmount(const ResourceType *rt); 392 bool hasUnitTypeWithResouceCost(const ResourceType *rt); 393 }; 394 395 }}//end namespace 396 397 #endif 398