mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-29 23:07:48 +02:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there. * Declared existing Entity APIs. * Added basic script context caching * Started Lua script module * Started Lua spell effect API * Started script state persistence * Started battle info callback binding * CommitPackage removed * Extracted spells::Caster to own header; Expanded Spell API. * implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C * !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented * Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key) * Re-enabled VERM macros. * !?GM0 added * !?TM implemented * Added !!MF:N * Started !?OB, !!BM, !!HE, !!OW, !!UN * Added basic support of w-variables * Added support for ERM indirect variables * Made !?FU regular trigger * !!re (ERA loop receiver) implemented * Fixed ERM receivers with zero args.
This commit is contained in:
253
scripting/lua/LuaStack.cpp
Normal file
253
scripting/lua/LuaStack.cpp
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* LuaStack.cpp, part of VCMI engine
|
||||
*
|
||||
* Authors: listed in file AUTHORS in main folder
|
||||
*
|
||||
* License: GNU General Public License v2.0 or later
|
||||
* Full text of license available in license.txt file, in main folder
|
||||
*
|
||||
*/
|
||||
#include "StdInc.h"
|
||||
|
||||
#include "LuaStack.h"
|
||||
|
||||
#include "../../lib/JsonNode.h"
|
||||
#include "../../lib/int3.h"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
|
||||
LuaStack::LuaStack(lua_State * L_)
|
||||
: L(L_)
|
||||
{
|
||||
initialTop = lua_gettop(L);
|
||||
}
|
||||
|
||||
void LuaStack::balance()
|
||||
{
|
||||
lua_settop(L, initialTop);
|
||||
}
|
||||
|
||||
void LuaStack::clear()
|
||||
{
|
||||
lua_settop(L, 0);
|
||||
}
|
||||
|
||||
void LuaStack::pushByIndex(lua_Integer index)
|
||||
{
|
||||
lua_pushvalue(L, index);
|
||||
}
|
||||
|
||||
void LuaStack::pushNil()
|
||||
{
|
||||
lua_pushnil(L);
|
||||
}
|
||||
|
||||
void LuaStack::pushInteger(lua_Integer value)
|
||||
{
|
||||
lua_pushinteger(L, value);
|
||||
}
|
||||
|
||||
void LuaStack::push(bool value)
|
||||
{
|
||||
lua_pushboolean(L, value);
|
||||
}
|
||||
|
||||
void LuaStack::push(const char * value)
|
||||
{
|
||||
lua_pushstring(L, value);
|
||||
}
|
||||
|
||||
void LuaStack::push(const std::string & value)
|
||||
{
|
||||
lua_pushlstring(L, value.c_str(), value.size());
|
||||
}
|
||||
|
||||
void LuaStack::push(const int3 & value)
|
||||
{
|
||||
push(value.x);
|
||||
push(value.y);
|
||||
push(value.z);
|
||||
}
|
||||
|
||||
void LuaStack::push(const JsonNode & value)
|
||||
{
|
||||
switch(value.getType())
|
||||
{
|
||||
case JsonNode::JsonType::DATA_BOOL:
|
||||
{
|
||||
push(value.Bool());
|
||||
}
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_FLOAT:
|
||||
{
|
||||
lua_pushnumber(L, value.Float());
|
||||
}
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_INTEGER:
|
||||
{
|
||||
pushInteger(value.Integer());
|
||||
}
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_STRUCT:
|
||||
{
|
||||
lua_newtable(L);
|
||||
for(auto & keyValue : value.Struct())
|
||||
{
|
||||
push(keyValue.first);
|
||||
push(keyValue.second);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_STRING:
|
||||
push(value.String());
|
||||
break;
|
||||
case JsonNode::JsonType::DATA_VECTOR:
|
||||
{
|
||||
lua_newtable(L);
|
||||
for(int idx = 0; idx < value.Vector().size(); idx++)
|
||||
{
|
||||
pushInteger(idx + 1);
|
||||
push(value.Vector()[idx]);
|
||||
lua_rawset(L, -3);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
pushNil();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool LuaStack::tryGet(int position, bool & value)
|
||||
{
|
||||
if(!lua_isboolean(L, position))
|
||||
return false;
|
||||
value = (lua_toboolean(L, position) != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaStack::tryGet(int position, double & value)
|
||||
{
|
||||
if(!lua_isnumber(L, position))
|
||||
return false;
|
||||
value = lua_tonumber(L, position);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaStack::tryGetInteger(int position, lua_Integer & value)
|
||||
{
|
||||
if(!lua_isnumber(L, position))
|
||||
return false;
|
||||
|
||||
value = lua_tointeger(L, position);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaStack::tryGet(int position, std::string & value)
|
||||
{
|
||||
if(!lua_isstring(L, position))
|
||||
return false;
|
||||
|
||||
size_t len = 0;
|
||||
auto raw = lua_tolstring(L, position, &len);
|
||||
value = std::string(raw, len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaStack::tryGet(int position, int3 & value)
|
||||
{
|
||||
return tryGet(position, value.x) && tryGet(position+1, value.y) && tryGet(position+2, value.z);
|
||||
}
|
||||
|
||||
bool LuaStack::tryGet(int position, JsonNode & value)
|
||||
{
|
||||
auto type = lua_type(L, position);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case LUA_TNIL:
|
||||
value.clear();
|
||||
return true;
|
||||
case LUA_TNUMBER:
|
||||
return tryGet(position, value.Float());
|
||||
case LUA_TBOOLEAN:
|
||||
value.Bool() = (lua_toboolean(L, position) != 0);
|
||||
return true;
|
||||
case LUA_TSTRING:
|
||||
return tryGet(position, value.String());
|
||||
case LUA_TTABLE:
|
||||
{
|
||||
JsonNode asVector(JsonNode::JsonType::DATA_VECTOR);
|
||||
JsonNode asStruct(JsonNode::JsonType::DATA_STRUCT);
|
||||
|
||||
lua_pushnil(L); /* first key */
|
||||
|
||||
while(lua_next(L, position) != 0)
|
||||
{
|
||||
/* 'key' (at index -2) and 'value' (at index -1) */
|
||||
|
||||
JsonNode fieldValue;
|
||||
if(!tryGet(lua_gettop(L), fieldValue))
|
||||
{
|
||||
lua_pop(L, 2);
|
||||
value.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
lua_pop(L, 1); //pop value
|
||||
|
||||
if(lua_type(L, -1) == LUA_TNUMBER)
|
||||
{
|
||||
auto key = lua_tointeger(L, -1);
|
||||
|
||||
if(key > 0)
|
||||
{
|
||||
if(asVector.Vector().size() < key)
|
||||
asVector.Vector().resize(key);
|
||||
--key;
|
||||
asVector.Vector().at(key) = fieldValue;
|
||||
}
|
||||
}
|
||||
else if(lua_isstring(L, -1))
|
||||
{
|
||||
std::string key;
|
||||
tryGet(-1, key);
|
||||
asStruct[key] = fieldValue;
|
||||
}
|
||||
}
|
||||
|
||||
if(!asVector.Vector().empty())
|
||||
{
|
||||
std::swap(value, asVector);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::swap(value, asStruct);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
value.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int LuaStack::retNil()
|
||||
{
|
||||
clear();
|
||||
pushNil();
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaStack::retVoid()
|
||||
{
|
||||
clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user