1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#ifndef SKIRMISH_AI_HANDLER_H
#define SKIRMISH_AI_HANDLER_H
#include <array>
#include "ExternalAI/SkirmishAIData.h"
#include "ExternalAI/SkirmishAIKey.h"
#include "Sim/Misc/GlobalConstants.h"
#include "System/creg/creg_cond.h"
#include "System/UnorderedMap.hpp"
#include "System/UnorderedSet.hpp"
class CGameSetup;
/**
* Handles all Skirmish AI instance relevant data, which includes,
* but is not limited to all sync relevant Skirmish AI stuff.
*/
class CSkirmishAIHandler
{
CR_DECLARE_STRUCT(CSkirmishAIHandler)
public:
void ResetState();
void LoadFromSetup(const CGameSetup& setup);
/**
* Will be called when the Mods archives were loaded into the VFS,
* and we received our player number (gu->myPlayerNum is set).
* This loads the list of Lua AIs from the mod archives LuaAI.lua.
*/
void LoadPreGame();
/**
* @param skirmishAIId index to check
* @return true if is active Skirmish AI
*
* Returns true if data for a Skirmish AI with the specified id is stored.
*/
bool IsActiveSkirmishAI(const size_t skirmishAIId) const;
/**
* @brief SkirmishAIData
* @param skirmishAIId index to fetch
* @return SkirmishAIData pointer
*
* Accesses the data of a Skirmish AI instance at a given index.
*/
SkirmishAIData* GetSkirmishAI(const size_t skirmishAIId);
/**
* @brief SkirmishAIData
* @param name name of the Skirmish AI instance
* @return its index or -1 if not found
*
* Search a Skirmish AI instance by name.
*/
size_t GetSkirmishAI(const std::string& name) const;
/**
* @brief Skirmish AIs controlling a team
*
* Will change during runtime (Connection lost, died, killed, created, ...).
*/
std::vector<uint8_t> GetSkirmishAIsInTeam(const int teamId, const int hostPlayerId = -1) const;
/**
* @brief Skirmish AIs hosted by a player
*
* Will change during runtime (Connection lost, died, killed, created, ...).
*/
std::vector<uint8_t> GetSkirmishAIsByPlayer(const int playerId) const;
/**
* @brief All active Skirmish AIs
*
* Will change during runtime (Connection lost, died, killed, created, ...).
*/
const spring::unordered_map<uint8_t, const SkirmishAIData*>& GetAllSkirmishAIs() const { return skirmishAIDataMap; }
/**
* @brief Adds a Skirmish AI
* @param data contans the details for the Skirmish AI to add
* @param skirmishAIId id of the Skirmish AI, generated by
* and received from the server
*/
bool AddSkirmishAI(const SkirmishAIData& data, const size_t skirmishAIId);
/**
* @brief Removes a Skirmish AI
* @param skirmishAIId id of the Skirmish AI to be removed
* @return true if the Skirmish AI was removed
*/
bool RemoveSkirmishAI(const size_t skirmishAIId);
bool HasSkirmishAIsInTeam(const int teamId, const int hostPlayerId = -1) const {
return (GetSkirmishAIsInTeam(teamId, hostPlayerId) != std::vector<uint8_t>{});
}
size_t GetNumSkirmishAIs() const { return numSkirmishAIs; }
// size_t GetNumSkirmishAIsInTeam(const int teamId, const int hostPlayerId = -1) const { ... }
/**
* Starts the initialization process of a locally running Skirmish AI,
* which was defined in the start script.
* Do NOT use for creating AIs not defined in the start script,
* as it will cuase desyncs.
* Stores detailed info locally real creation happens right here.
* @param skirmishAIId Skirmish AI index
* @see EngineOutHandler::CreateSkirmishAI()
*/
void CreateLocalSkirmishAI(const size_t skirmishAIId);
/**
* Starts the synced initialization process of a locally running Skirmish AI.
* Stores detailed info locally and sends synced stuff in a message
* to the server, and real creation will happen when receiving the answer.
* @param aiData detailed info of the AI to create
* @see EngineOutHandler::CreateSkirmishAI()
*/
void NetCreateLocalSkirmishAI(const SkirmishAIData& aiData);
/**
* Returns detailed (including unsynced) data for a Skirmish AI to be
* running on the local machine.
* @param teamId index of the team the AI shall be created for.
* only one AI per player can be in creation
* @return detailed (including unsynced) data for a Skirmish AI
* @see CreateLocalSkirmishAI()
*/
const SkirmishAIData* GetLocalSkirmishAIInCreation(const int teamId) const;
/**
* This may only be called for local AIs.
* Sends a message to the server, while real destruction will happen
* when receiving the answer.
* @param skirmishAIId index of the AI to destroy
* @param reason for a list of values, see SReleaseEvent in ExternalAI/Interface/AISEvents.h
* @see EngineOutHandler::DestroySkirmishAI()
*/
void SetLocalKillFlag(const size_t skirmishAIId, const int reason);
/**
* Returns a value explaining why a Skirmish AI was killed, or a value < 0
* if it is not.
* @param skirmishAIId index of the AI in question
* @return for a list of values, see SReleaseEvent in ExternalAI/Interface/AISEvents.h
* @see HasLocalKillFlag()
*/
int GetLocalKillFlag(const size_t skirmishAIId) const { return aiKillFlags[skirmishAIId]; }
/**
* Reports true even before the DIEING state was received
* from the server, but only for local AIs.
* @param skirmishAIId index of the AI in question
*/
bool HasLocalKillFlag(const size_t skirmishAIId) const { return (GetLocalKillFlag(skirmishAIId) != -1); }
bool IsLocalSkirmishAI(const size_t skirmishAIId) const;
/**
* Returns the library key for a local Skirmish AI, or NULL.
*/
const SkirmishAIKey* GetLocalSkirmishAILibraryKey(const size_t skirmishAIId);
const spring::unordered_set<std::string>& GetLuaAIImplShortNames() const { return luaAIShortNames; }
uint8_t GetCurrentAIID() { return currentAIId; }
void SetCurrentAIID(uint8_t id) { currentAIId = id; }
private:
static bool IsLocalSkirmishAI(const SkirmishAIData& aiData);
static bool IsValidSkirmishAI(const SkirmishAIData& aiData) { return (!aiData.shortName.empty()); }
bool IsLuaAI(const SkirmishAIData& aiData) const { return (luaAIShortNames.find(aiData.shortName) != luaAIShortNames.end()); }
void CompleteWithDefaultOptionValues(const size_t skirmishAIId);
void CompleteSkirmishAI(const size_t skirmishAIId);
/// id -> AI instance
std::array<SkirmishAIData, MAX_AIS> aiInstanceData;
/// id -> AI instance library key
std::array<SkirmishAIKey, MAX_AIS> aiLibraryKeys;
/// temporarily stores detailed info of local Skirmish AIs waiting for initialization
std::array<SkirmishAIData, MAX_AIS> localTeamAIs;
/// temporarily stores reason for killing a Skirmish AI
std::array<int, MAX_AIS> aiKillFlags;
spring::unordered_map<uint8_t, const SkirmishAIData*> skirmishAIDataMap;
spring::unordered_set<std::string> luaAIShortNames;
// the current local AI ID that is executing, MAX_AIS if none (e.g. LuaUI)
uint8_t currentAIId = MAX_AIS;
uint8_t numSkirmishAIs = 0;
bool gameInitialized = false;
};
extern CSkirmishAIHandler skirmishAIHandler;
#endif // SKIRMISH_AI_HANDLER_H
|