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 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
|
/* This file is part of the Spring engine (GPL v2 or later), see LICENSE.html */
#ifndef LUA_UTILS_H
#define LUA_UTILS_H
#include <string>
#include <vector>
using std::string;
using std::vector;
#include "LuaHashString.h"
#include "LuaInclude.h"
#include "LuaHandle.h"
#include "LuaDefs.h"
// FIXME: use fwd-decls
#include "Sim/Units/CommandAI/Command.h"
#include "Sim/Features/Feature.h"
#include "Sim/Units/Unit.h"
#include "Sim/Misc/TeamHandler.h"
#include "System/EventClient.h"
// is defined as macro on FreeBSD (wtf)
#ifdef isnumber
#undef isnumber
#endif
struct SolidObjectDef;
struct SCommandDescription;
class LuaUtils {
public:
struct ScopedStackChecker {
public:
ScopedStackChecker(lua_State* L, int returnVars = 0);
~ScopedStackChecker();
private:
lua_State* luaState;
int prevTop;
int returnVars;
};
struct ScopedDebugTraceBack {
public:
ScopedDebugTraceBack(lua_State* L);
~ScopedDebugTraceBack();
void SetErrFuncIdx(int idx) { errFuncIdx = idx; }
int GetErrFuncIdx() const { return errFuncIdx; }
private:
lua_State* L;
int errFuncIdx;
};
public:
struct DataDump {
int type;
std::string str;
float num;
bool bol;
std::vector<std::pair<DataDump, DataDump> > table;
};
struct ShallowDataDump {
int type;
union {
std::string *str;
float num;
bool bol;
} data;
};
public:
// Backups lua data into a c++ vector and restores it from it
static int exportedDataSize; //< performance stat
static int Backup(std::vector<DataDump> &backup, lua_State* src, int count);
static int Restore(const std::vector<DataDump> &backup, lua_State* dst);
// Copies lua data between 2 lua_States
static int CopyData(lua_State* dst, lua_State* src, int count);
// returns stack index of traceback function
static int PushDebugTraceback(lua_State* L);
// lower case all keys in the table, with recursion
static bool LowerKeys(lua_State* L, int tableIndex);
static bool CheckTableForNaNs(lua_State* L, int table, const std::string& name);
static int PushModelHeight(lua_State* L, const SolidObjectDef* def, bool isUnitDef);
static int PushModelRadius(lua_State* L, const SolidObjectDef* def, bool isUnitDef);
static int PushFeatureModelDrawType(lua_State* L, const FeatureDef* def);
static int PushModelName(lua_State* L, const SolidObjectDef* def);
static int PushModelTable(lua_State* L, const SolidObjectDef* def);
static int PushColVolTable(lua_State* L, const CollisionVolume* vol);
static void PushCommandParamsTable(lua_State* L, const Command& cmd, bool subtable);
static void PushCommandOptionsTable(lua_State* L, const Command& cmd, bool subtable);
static void PushUnitAndCommand(lua_State* L, const CUnit* unit, const Command& cmd);
// from LuaUI.cpp / LuaSyncedCtrl.cpp (used to be duplicated)
static void ParseCommandOptions(lua_State* L, Command& cmd, const char* caller, int index);
static Command ParseCommand(lua_State* L, const char* caller, int idIndex);
static Command ParseCommandTable(lua_State* L, const char* caller, int table);
static void ParseCommandArray(lua_State* L, const char* caller, int table, vector<Command>& commands);
static int ParseFacing(lua_State* L, const char* caller, int index);
static void PushCurrentFuncEnv(lua_State* L, const char* caller);
static void* GetUserData(lua_State* L, int index, const string& type);
static void PrintStack(lua_State* L);
// from LuaFeatureDefs.cpp / LuaUnitDefs.cpp / LuaWeaponDefs.cpp
// (helper for the Next() iteration routine)
static int Next(const ParamMap& paramMap, lua_State* L);
// from LuaParser.cpp / LuaUnsyncedCtrl.cpp
// (implementation copied from lua/src/lib/lbaselib.c)
static int Echo(lua_State* L);
static int Log(lua_State* L);
static bool PushLogEntries(lua_State* L);
static bool PushCustomBaseFunctions(lua_State* L);
static int ParseIntArray(lua_State* L, int tableIndex,
int* array, int arraySize);
static int ParseFloatArray(lua_State* L, int tableIndex,
float* array, int arraySize);
static int ParseStringArray(lua_State* L, int tableIndex,
string* array, int arraySize);
static int ParseIntVector(lua_State* L, int tableIndex,
vector<int>& vec);
static int ParseFloatVector(lua_State* L, int tableIndex,
vector<float>& vec);
static int ParseStringVector(lua_State* L, int tableIndex,
vector<string>& vec);
static void PushStringVector(lua_State* L, const vector<string>& vec);
static void PushCommandDesc(lua_State* L, const SCommandDescription& cd);
};
template<typename ObjectDefType, size_t indxFuncsSize, size_t iterFuncsSize>
static void PushObjectDefProxyTable(
lua_State* L,
const std::array<const LuaHashString, indxFuncsSize>& indxOpers,
const std::array<const LuaHashString, iterFuncsSize>& iterOpers,
const std::array<const lua_CFunction, indxFuncsSize>& indxFuncs,
const std::array<const lua_CFunction, iterFuncsSize>& iterFuncs,
const ObjectDefType* def
) {
lua_pushnumber(L, def->id);
lua_newtable(L); { // the proxy table
lua_newtable(L); // the metatable
for (size_t n = 0; n < indxFuncsSize; n++) {
indxOpers[n].Push(L);
lua_pushlightuserdata(L, (void*) def);
lua_pushcclosure(L, indxFuncs[n], 1);
lua_rawset(L, -3); // closure
}
lua_setmetatable(L, -2);
}
for (size_t n = 0; n < iterFuncsSize; n++) {
iterOpers[n].Push(L);
lua_pushcfunction(L, iterFuncs[n]);
lua_rawset(L, -3);
}
lua_rawset(L, -3); // set the proxy table
}
static inline void LuaPushNamedNil(lua_State* L,
const string& key)
{
lua_pushsstring(L, key);
lua_pushnil(L);
lua_rawset(L, -3);
}
static inline void LuaPushNamedBool(lua_State* L,
const string& key, bool value)
{
lua_pushsstring(L, key);
lua_pushboolean(L, value);
lua_rawset(L, -3);
}
static inline void LuaPushNamedNumber(lua_State* L,
const string& key, lua_Number value)
{
lua_pushsstring(L, key);
lua_pushnumber(L, value);
lua_rawset(L, -3);
}
static inline void LuaPushNamedString(lua_State* L,
const string& key, const string& value)
{
lua_pushsstring(L, key);
lua_pushsstring(L, value);
lua_rawset(L, -3);
}
static inline void LuaPushNamedCFunc(lua_State* L,
const string& key, int (*func)(lua_State*))
{
lua_pushsstring(L, key);
lua_pushcfunction(L, func);
lua_rawset(L, -3);
}
static inline void LuaInsertDualMapPair(lua_State* L, const string& name, int number)
{
lua_pushsstring(L, name);
lua_pushnumber(L, number);
lua_rawset(L, -3);
lua_pushnumber(L, number);
lua_pushsstring(L, name);
lua_rawset(L, -3);
}
static inline bool FullCtrl(const lua_State* L)
{
return CLuaHandle::GetHandleFullCtrl(L);
}
static inline int CtrlTeam(const lua_State* L)
{
return CLuaHandle::GetHandleCtrlTeam(L);
}
static inline int CtrlAllyTeam(const lua_State* L)
{
const int ctrlTeam = CtrlTeam(L);
if (ctrlTeam < 0)
return ctrlTeam;
return teamHandler->AllyTeam(ctrlTeam);
}
static inline bool CanControlTeam(const lua_State* L, int teamID)
{
const int ctrlTeam = CtrlTeam(L);
if (ctrlTeam < 0)
return (ctrlTeam == CEventClient::AllAccessTeam);
return (ctrlTeam == teamID);
}
static inline bool CanControlAllyTeam(const lua_State* L, int allyTeamID)
{
const int ctrlTeam = CtrlTeam(L);
if (ctrlTeam < 0)
return (ctrlTeam == CEventClient::AllAccessTeam);
return (teamHandler->AllyTeam(ctrlTeam) == allyTeamID);
}
static inline bool CanControlFeatureAllyTeam(const lua_State* L, int allyTeamID)
{
const int ctrlTeam = CtrlTeam(L);
if (ctrlTeam < 0)
return (ctrlTeam == CEventClient::AllAccessTeam);
if (allyTeamID < 0)
return (ctrlTeam == teamHandler->GaiaTeamID());
return (teamHandler->AllyTeam(ctrlTeam) == allyTeamID);
}
static inline bool CanControlProjectileAllyTeam(const lua_State* L, int allyTeamID)
{
const int ctrlTeam = CtrlTeam(L);
if (ctrlTeam < 0)
return (ctrlTeam == CEventClient::AllAccessTeam);
if (allyTeamID < 0)
return false;
return (teamHandler->AllyTeam(ctrlTeam) == allyTeamID);
}
static inline bool CanControlUnit(const lua_State* L, const CUnit* unit)
{
const int ctrlTeam = CtrlTeam(L);
if (ctrlTeam < 0)
return (ctrlTeam == CEventClient::AllAccessTeam);
return (ctrlTeam == unit->team);
}
static inline bool CanControlFeature(const lua_State* L, const CFeature* feature)
{
return CanControlFeatureAllyTeam(L, feature->allyteam);
}
static inline const LocalModelPiece* ParseObjectConstLocalModelPiece(lua_State* L, const CSolidObject* obj, int pieceArg)
{
assert(obj != nullptr);
const unsigned int pieceIdx = luaL_checkint(L, pieceArg) - 1;
// automatically false if LM was not initialized
if (!obj->localModel.HasPiece(pieceIdx))
return nullptr;
return (obj->localModel.GetPiece(pieceIdx));
}
static inline LocalModelPiece* ParseObjectLocalModelPiece(lua_State* L, CSolidObject* obj, int pieceArg)
{
return (const_cast<LocalModelPiece*>(ParseObjectConstLocalModelPiece(L, obj, pieceArg)));
}
#endif // LUA_UTILS_H
|