diff --git a/rts/ExternalAI/Interface/AISCommands.h b/rts/ExternalAI/Interface/AISCommands.h index e6a2b993ffd..61965e81d19 100644 --- a/rts/ExternalAI/Interface/AISCommands.h +++ b/rts/ExternalAI/Interface/AISCommands.h @@ -600,7 +600,7 @@ struct SBuildUnitCommand { int timeOut; int toBuildUnitDefId; - float* buildPos_posF3; + const float* buildPos_posF3; /// set it to UNIT_COMMAND_BUILD_NO_FACING, if you do not want to specify a certain facing int facing; }; //$ COMMAND_UNIT_BUILD Unit_build REF:toBuildUnitDefId->UnitDef @@ -760,7 +760,7 @@ struct SMoveUnitCommand { */ int timeOut; - float* toPos_posF3; + const float* toPos_posF3; }; //$ COMMAND_UNIT_MOVE Unit_moveTo struct SPatrolUnitCommand { @@ -778,7 +778,7 @@ struct SPatrolUnitCommand { */ int timeOut; - float* toPos_posF3; + const float* toPos_posF3; }; //$ COMMAND_UNIT_PATROL Unit_patrolTo struct SFightUnitCommand { @@ -796,7 +796,7 @@ struct SFightUnitCommand { */ int timeOut; - float* toPos_posF3; + const float* toPos_posF3; }; //$ COMMAND_UNIT_FIGHT Unit_fight struct SAttackUnitCommand { @@ -834,7 +834,7 @@ struct SAttackAreaUnitCommand { */ int timeOut; - float* toAttackPos_posF3; + const float* toAttackPos_posF3; float radius; }; //$ COMMAND_UNIT_ATTACK_AREA Unit_attackArea @@ -994,7 +994,7 @@ struct SSetBaseUnitCommand { */ int timeOut; - float* basePos_posF3; + const float* basePos_posF3; }; //$ COMMAND_UNIT_SET_BASE Unit_setBase //struct SInternalUnitCommand { @@ -1065,7 +1065,7 @@ struct SLoadUnitsAreaUnitCommand { */ int timeOut; - float* pos_posF3; + const float* pos_posF3; float radius; }; //$ COMMAND_UNIT_LOAD_UNITS_AREA Unit_loadUnitsInArea @@ -1102,7 +1102,7 @@ struct SUnloadUnitCommand { */ int timeOut; - float* toPos_posF3; + const float* toPos_posF3; int toUnloadUnitId; }; //$ COMMAND_UNIT_UNLOAD_UNIT Unit_unload REF:toUnloadUnitId->Unit @@ -1121,7 +1121,7 @@ struct SUnloadUnitsAreaUnitCommand { */ int timeOut; - float* toPos_posF3; + const float* toPos_posF3; float radius; }; //$ COMMAND_UNIT_UNLOAD_UNITS_AREA Unit_unloadUnitsInArea @@ -1194,7 +1194,7 @@ struct SReclaimAreaUnitCommand { */ int timeOut; - float* pos_posF3; + const float* pos_posF3; float radius; }; //$ COMMAND_UNIT_RECLAIM_AREA Unit_reclaimInArea @@ -1265,7 +1265,7 @@ struct SDGunPosUnitCommand { */ int timeOut; - float* pos_posF3; + const float* pos_posF3; }; //$ COMMAND_UNIT_D_GUN_POS Unit_dGunPosition struct SRestoreAreaUnitCommand { @@ -1283,7 +1283,7 @@ struct SRestoreAreaUnitCommand { */ int timeOut; - float* pos_posF3; + const float* pos_posF3; float radius; }; //$ COMMAND_UNIT_RESTORE_AREA Unit_restoreArea @@ -1358,7 +1358,7 @@ struct SResurrectAreaUnitCommand { */ int timeOut; - float* pos_posF3; + const float* pos_posF3; float radius; }; //$ COMMAND_UNIT_RESURRECT_AREA Unit_resurrectInArea @@ -1395,7 +1395,7 @@ struct SCaptureAreaUnitCommand { */ int timeOut; - float* pos_posF3; + const float* pos_posF3; float radius; }; //$ COMMAND_UNIT_CAPTURE_AREA Unit_captureInArea @@ -1469,7 +1469,7 @@ struct SCustomUnitCommand { int timeOut; int cmdId; - float* params; + const float* params; int params_size; }; //$ COMMAND_UNIT_CUSTOM Unit_executeCustomCommand ARRAY:params diff --git a/rts/Sim/Units/CommandAI/Command.cpp b/rts/Sim/Units/CommandAI/Command.cpp index 2e7ac0de203..ab3fac237f2 100644 --- a/rts/Sim/Units/CommandAI/Command.cpp +++ b/rts/Sim/Units/CommandAI/Command.cpp @@ -1,6 +1,9 @@ /* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ #include "Command.h" +#include "CommandParamsPool.hpp" + +CommandParamsPool cmdParamsPool; CR_BIND(Command, ) CR_REG_METADATA(Command, ( @@ -14,3 +17,67 @@ CR_REG_METADATA(Command, ( CR_MEMBER(params) )) + +Command::~Command() { + if (!IsPooledCommand()) + return; + + cmdParamsPool.ReleasePage(pageIndex); +} + + +const float* Command::GetParams(unsigned int idx) const { + if (idx >= numParams) + return nullptr; + + if (IsPooledCommand()) { + assert(numParams > MAX_COMMAND_PARAMS); + return (cmdParamsPool.GetPtr(pageIndex, idx)); + } + + return ((idx < MAX_COMMAND_PARAMS)? ¶ms[idx]: nullptr); +} + +float Command::GetParam(unsigned int idx) const { + const float* ptr = GetParams(idx); + + if (ptr != nullptr) + return *ptr; + + return 0.0f; +} + + +bool Command::SetParam(unsigned int idx, float param) { + float* ptr = const_cast(GetParams(idx)); + + if (ptr != nullptr) + return (*ptr = param, true); + + return false; +} + +bool Command::PushParam(float param) { + if (numParams < MAX_COMMAND_PARAMS) { + // no need to make this a pooled command just yet + params[numParams++] = param; + return true; + } + + if (!IsPooledCommand()) { + // not in the pool, reserve an entry and fill it + pageIndex = cmdParamsPool.AcquirePage(); + + for (unsigned int i = 0; i < numParams; i++) { + cmdParamsPool.Push(pageIndex, params[i]); + } + + memset(¶ms[0], 0, sizeof(params)); + assert(IsPooledCommand()); + } + + // add new parameter + numParams = cmdParamsPool.Push(pageIndex, param); + return true; +} + diff --git a/rts/Sim/Units/CommandAI/Command.h b/rts/Sim/Units/CommandAI/Command.h index b408cb8923b..6ddadbcd3b5 100644 --- a/rts/Sim/Units/CommandAI/Command.h +++ b/rts/Sim/Units/CommandAI/Command.h @@ -97,16 +97,10 @@ #define CONTROL_KEY (1 << 6) // 64 #define ALT_KEY (1 << 7) // 128 -// maximum number of parameters for any (default and custom) command type -#define MAX_COMMAND_PARAMS 10 +// maximum number of inline parameters for any (default and custom) command type +#define MAX_COMMAND_PARAMS 8 -#ifdef __GNUC__ - #define _deprecated __attribute__ ((deprecated)) -#else - #define _deprecated -#endif - #if defined(BUILDING_AI) #define CMD_DGUN CMD_MANUALFIRE #endif @@ -137,6 +131,7 @@ extern "C" { int id[2]; int timeOut; + unsigned int pageIndex; unsigned int numParams; /// unique id within a CCommandQueue @@ -156,15 +151,13 @@ extern "C" { -struct Command -{ +struct Command { private: CR_DECLARE_STRUCT(Command) public: - Command() - { - memset(params, 0, sizeof(params)); + Command() { + memset(¶ms[0], 0, sizeof(params)); SetFlags(INT_MAX, 0, 0); } @@ -174,76 +167,68 @@ struct Command } Command& operator = (const Command& c) { - id[0] = c.id[0]; - id[1] = c.id[1]; - numParams = c.numParams; + memcpy(&id[0], &c.id[0], sizeof(id)); SetFlags(c.timeOut, c.tag, c.options); CopyParams(c); return *this; } - Command(const float3& pos) - { - memset(params, 0, sizeof(params)); + Command(const float3& pos) { + memset(¶ms[0], 0, sizeof(params)); PushPos(pos); SetFlags(INT_MAX, 0, 0); } - Command(int cmdID) - { - memcpy(id, &cmdID, sizeof(cmdID)); - memset(params, 0, sizeof(params)); + Command(int cmdID) { + memcpy(&id[0], &cmdID, sizeof(cmdID)); + memset(¶ms[0], 0, sizeof(params)); SetFlags(INT_MAX, 0, 0); } - Command(int cmdID, const float3& pos) - { - memcpy(id, &cmdID, sizeof(cmdID)); - memset(params, 0, sizeof(params)); + Command(int cmdID, const float3& pos) { + memcpy(&id[0], &cmdID, sizeof(cmdID)); + memset(¶ms[0], 0, sizeof(params)); PushPos(pos); SetFlags(INT_MAX, 0, 0); } - Command(int cmdID, unsigned char cmdOptions) - { - memcpy(id, &cmdID, sizeof(cmdID)); - memset(params, 0, sizeof(params)); + Command(int cmdID, unsigned char cmdOptions) { + memcpy(&id[0], &cmdID, sizeof(cmdID)); + memset(¶ms[0], 0, sizeof(params)); SetFlags(INT_MAX, 0, cmdOptions); } - Command(int cmdID, unsigned char cmdOptions, float param) - { - memcpy(id, &cmdID, sizeof(cmdID)); - memset(params, 0, sizeof(params)); + Command(int cmdID, unsigned char cmdOptions, float param) { + memcpy(&id[0], &cmdID, sizeof(cmdID)); + memset(¶ms[0], 0, sizeof(params)); PushParam(param); SetFlags(INT_MAX, 0, cmdOptions); } - Command(int cmdID, unsigned char cmdOptions, const float3& pos) - { - memcpy(id, &cmdID, sizeof(cmdID)); - memset(params, 0, sizeof(params)); + Command(int cmdID, unsigned char cmdOptions, const float3& pos) { + memcpy(&id[0], &cmdID, sizeof(cmdID)); + memset(¶ms[0], 0, sizeof(params)); PushPos(pos); SetFlags(INT_MAX, 0, cmdOptions); } - Command(int cmdID, unsigned char cmdOptions, float param, const float3& pos) - { - memcpy(id, &cmdID, sizeof(cmdID)); - memset(params, 0, sizeof(params)); + Command(int cmdID, unsigned char cmdOptions, float param, const float3& pos) { + memcpy(&id[0], &cmdID, sizeof(cmdID)); + memset(¶ms[0], 0, sizeof(params)); PushParam(param); PushPos(pos); SetFlags(INT_MAX, 0, cmdOptions); } + ~Command(); RawCommand ToRawCommand() { @@ -252,60 +237,67 @@ struct Command rc.id[1] = id[1]; rc.timeOut = timeOut; - rc.numParams = numParams; - rc.tag = tag; - rc.options = options; - rc.params = ¶ms[0]; + rc.pageIndex = pageIndex; + rc.numParams = numParams; + rc.tag = tag; + rc.options = options; + + rc.params = const_cast(GetParams()); return rc; } void FromRawCommand(const RawCommand& rc) { - id[0] = rc.id[0]; - id[1] = rc.id[1]; + pageIndex = rc.pageIndex; numParams = rc.numParams; - memset(params, 0, sizeof(params)); + memcpy(&id[0], &rc.id[0], sizeof(id)); + memset(¶ms[0], 0, sizeof(params)); + SetFlags(rc.timeOut, rc.tag, rc.options); - for (unsigned int n = 0; n < rc.numParams; n++) { - PushParam(rc.params[n]); + if (IsPooledCommand()) { + // actual params should still be in pool, original command exists on AI side + assert(numParams > MAX_COMMAND_PARAMS); + return; } + + assert(numParams <= MAX_COMMAND_PARAMS); + memcpy(¶ms[0], &rc.params[0], rc.numParams); } // returns true if the command references another object and // in this case also returns the param index of the object in cpos bool IsObjectCommand(int& cpos) const { - const unsigned int psize = numParams; - switch (GetID()) { case CMD_ATTACK: case CMD_FIGHT: case CMD_MANUALFIRE: cpos = 0; - return (1 <= psize && psize < 3); + return (1 <= numParams && numParams < 3); case CMD_GUARD: case CMD_LOAD_ONTO: cpos = 0; - return (psize >= 1); + return (numParams >= 1); case CMD_CAPTURE: case CMD_LOAD_UNITS: case CMD_RECLAIM: case CMD_REPAIR: case CMD_RESURRECT: cpos = 0; - return (1 <= psize && psize < 4); + return (1 <= numParams && numParams < 4); case CMD_UNLOAD_UNIT: cpos = 3; - return (psize >= 4); + return (numParams >= 4); case CMD_INSERT: { - if (psize < 3) + if (numParams < 3) return false; - Command icmd((int)params[1], (unsigned char)params[2]); + Command icmd(static_cast(GetParam(1)), static_cast(GetParam(2))); - for (unsigned int p = 3; p < psize; p++) - icmd.PushParam(params[p]); + for (unsigned int p = 3; p < numParams; p++) { + icmd.PushParam(GetParam(p)); + } if (!icmd.IsObjectCommand(cpos)) return false; @@ -314,6 +306,7 @@ struct Command return true; } } + return false; } @@ -345,12 +338,13 @@ struct Command case CMD_WAIT: return false; - default: - // build commands are no different from reclaim or repair commands - // in that they can require a unit to move, so return true when we - // have one - return IsBuildCommand(); + default: break; } + + // build commands are no different from reclaim or repair commands + // in that they can require a unit to move, so return true when we + // have one + return IsBuildCommand(); } bool IsAreaCommand() const { @@ -366,64 +360,51 @@ struct Command return (numParams == 5); case CMD_AREA_ATTACK: return true; + + default: break; } + return false; } bool IsBuildCommand() const { return (GetID() < 0); } bool IsEmptyCommand() const { return (numParams == 0); } + bool IsPooledCommand() const { return (pageIndex != -1u); } // implies numParams > MAX_COMMAND_PARAMS int GetID(bool idx = false) const { return id[idx]; } int GetTimeOut() const { return timeOut; } + unsigned int GetpageIndex() const { return pageIndex; } unsigned int GetNumParams() const { return numParams; } unsigned int GetTag() const { return tag; } unsigned char GetOpts() const { return options; } - const float* GetParams() const { return ¶ms[0]; } - float GetParam(unsigned int idx) const { return ((idx >= numParams)? 0.0f: params[idx]); } + const float* GetParams(unsigned int idx = 0) const; + float GetParam (unsigned int idx ) const; - bool SetParam(unsigned int idx, float param) { - if (idx >= numParams) - return false; - params[idx] = param; - return true; - } - bool PushParam(float param) { - if (numParams >= MAX_COMMAND_PARAMS) - return false; - params[numParams++] = param; - return true; - } + bool SetParam(unsigned int idx, float param); + bool PushParam(float param); bool PushPos(const float3& pos) { return (PushPos(&pos.x)); } bool PushPos(const float* pos) { - if ((numParams + 3) > MAX_COMMAND_PARAMS) - return false; - - params[numParams++] = pos[0]; - params[numParams++] = pos[1]; - params[numParams++] = pos[2]; + PushParam(pos[0]); + PushParam(pos[1]); + PushParam(pos[2]); return true; } float3 GetPos(unsigned int idx) const { float3 p; - if ((idx + 3) > numParams) - return p; - p.x = params[idx + 0]; - p.y = params[idx + 1]; - p.z = params[idx + 2]; + p.x = GetParam(idx + 0); + p.y = GetParam(idx + 1); + p.z = GetParam(idx + 2); return p; } bool SetPos(unsigned int idx, const float3& p) { - if ((idx + 3) > numParams) - return false; - - params[idx + 0] = p.x; - params[idx + 1] = p.y; - params[idx + 2] = p.z; + SetParam(idx + 0, p.x); + SetParam(idx + 1, p.y); + SetParam(idx + 2, p.z); return true; } @@ -438,8 +419,11 @@ struct Command } void CopyParams(const Command& c) { - memset(params, 0, sizeof(params)); - memcpy(params, c.params, sizeof(params)); + assert(IsEmptyCommand()); + + for (unsigned int i = 0; i < c.numParams; i++) { + PushParam(c.GetParam(i)); + } } private: @@ -458,6 +442,8 @@ struct Command */ int timeOut = INT_MAX; + /// page-index for cmdParamsPool, valid iff numParams > MAX_COMMAND_PARAMS + unsigned int pageIndex = -1u; unsigned int numParams = 0; /// unique id within a CCommandQueue @@ -466,8 +452,9 @@ struct Command /// option bits (RIGHT_MOUSE_KEY, ...) unsigned char options = 0; - /// command parameters + /// inline command parameters, used if numParams <= MAX_COMMAND_PARAMS float params[MAX_COMMAND_PARAMS]; }; #endif // COMMAND_H + diff --git a/rts/Sim/Units/CommandAI/CommandAI.cpp b/rts/Sim/Units/CommandAI/CommandAI.cpp index 95e1ac02a97..3508edcfafb 100644 --- a/rts/Sim/Units/CommandAI/CommandAI.cpp +++ b/rts/Sim/Units/CommandAI/CommandAI.cpp @@ -970,8 +970,7 @@ void CCommandAI::GiveAllowedCommand(const Command& c, bool fromSynced) bool first; if (CancelCommands(c, commandQue, first) > 0) { if (first) { - Command stopCommand(CMD_STOP); - commandQue.push_front(stopCommand); + commandQue.push_front(Command(CMD_STOP)); SlowUpdate(); } return; diff --git a/rts/Sim/Units/CommandAI/CommandParamsPool.hpp b/rts/Sim/Units/CommandAI/CommandParamsPool.hpp new file mode 100644 index 00000000000..2755bc5ab0c --- /dev/null +++ b/rts/Sim/Units/CommandAI/CommandParamsPool.hpp @@ -0,0 +1,62 @@ +/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */ + +#ifndef COMMAND_PARAMS_POOL_H +#define COMMAND_PARAMS_POOL_H + +#include +#include +#include + +template struct TCommandParamsPool { +public: + const T* GetPtr(unsigned int i, unsigned int j ) const { assert(i < pages.size()); return (pages[i].data( ) + j); } + // T* GetPtr(unsigned int i, unsigned int j ) { assert(i < pages.size()); return (pages[i].data( ) + j); } + T Get (unsigned int i, unsigned int j ) const { assert(i < pages.size()); return (pages[i].at (j) ); } + T Set (unsigned int i, unsigned int j, T v) { assert(i < pages.size()); return (pages[i].at (j) = v); } + + size_t Push(unsigned int i, T v) { + assert(i < pages.size()); + pages[i].push_back(v); + return (pages[i].size()); + } + + void ReleasePage(unsigned int i) { + assert(i < pages.size()); + indcs.push_back(i); + } + + unsigned int AcquirePage() { + if (indcs.empty()) { + const size_t numIndices = indcs.size(); + + pages.resize(std::max(N, pages.size() << 1)); + indcs.resize(std::max(N, indcs.size() << 1)); + + const auto beg = indcs.begin() + numIndices; + const auto end = indcs.end(); + + // generate new indices + std::for_each(beg, end, [&](const unsigned int& i) { indcs[&i - &indcs[0]] = &i - &indcs[0]; }); + } + + const unsigned int pageIndex = indcs.back(); + + pages[pageIndex].clear(); + pages[pageIndex].reserve(S); + + indcs.pop_back(); + return pageIndex; + } + +private: + std::vector< std::vector > pages; + std::vector indcs; +}; + +typedef TCommandParamsPool CommandParamsPool; + + +extern CommandParamsPool cmdParamsPool; + +#endif + diff --git a/rts/System/MainDefines.h b/rts/System/MainDefines.h index cdc3337824e..a421ac8b0c1 100644 --- a/rts/System/MainDefines.h +++ b/rts/System/MainDefines.h @@ -68,6 +68,13 @@ #endif +#ifdef __GNUC__ + #define _deprecated __attribute__ ((deprecated)) +#else + #define _deprecated +#endif + + #ifdef _MSC_VER /* Microsoft Visual C++ 7.0: MSC_VER = 1300 Microsoft Visual C++ 7.1: MSC_VER = 1310 */