LuaState: Added support for config-style usage.
Globals and table values can be queried from the Lua state easily. Use perfect forwarding.
This commit is contained in:
parent
813ca04676
commit
c6012a95bd
@ -211,23 +211,31 @@ void cLuaState::AddPackagePath(const AString & a_PathVariable, const AString & a
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cLuaState::LoadFile(const AString & a_FileName)
|
bool cLuaState::LoadFile(const AString & a_FileName, bool a_LogWarnings)
|
||||||
{
|
{
|
||||||
ASSERT(IsValid());
|
ASSERT(IsValid());
|
||||||
|
|
||||||
// Load the file:
|
// Load the file:
|
||||||
int s = luaL_loadfile(m_LuaState, a_FileName.c_str());
|
int s = luaL_loadfile(m_LuaState, a_FileName.c_str());
|
||||||
if (ReportErrors(s))
|
if (s != 0)
|
||||||
{
|
{
|
||||||
LOGWARNING("Can't load %s because of an error in file %s", m_SubsystemName.c_str(), a_FileName.c_str());
|
if (a_LogWarnings)
|
||||||
|
{
|
||||||
|
LOGWARNING("Can't load %s because of a load error in file %s: %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1));
|
||||||
|
}
|
||||||
|
lua_pop(m_LuaState, 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute the globals:
|
// Execute the globals:
|
||||||
s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0);
|
s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0);
|
||||||
if (ReportErrors(s))
|
if (s != 0)
|
||||||
{
|
{
|
||||||
LOGWARNING("Error in %s in file %s", m_SubsystemName.c_str(), a_FileName.c_str());
|
if (a_LogWarnings)
|
||||||
|
{
|
||||||
|
LOGWARNING("Can't load %s because of an initialization error in file %s: %d (%s)", m_SubsystemName.c_str(), a_FileName.c_str(), s, lua_tostring(m_LuaState, -1));
|
||||||
|
}
|
||||||
|
lua_pop(m_LuaState, 1);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,6 +454,18 @@ void cLuaState::Push(const cPlayer * a_Player)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cLuaState::Push(const cLuaState::cRef & a_Ref)
|
||||||
|
{
|
||||||
|
ASSERT(IsValid());
|
||||||
|
|
||||||
|
lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, static_cast<int>(a_Ref));
|
||||||
|
m_NumCurrentFunctionArgs += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cLuaState::Push(const HTTPRequest * a_Request)
|
void cLuaState::Push(const HTTPRequest * a_Request)
|
||||||
{
|
{
|
||||||
ASSERT(IsValid());
|
ASSERT(IsValid());
|
||||||
@ -765,14 +785,17 @@ bool cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal)
|
bool cLuaState::GetStackValue(int a_StackPos, eBlockFace & a_ReturnedVal)
|
||||||
{
|
{
|
||||||
if (lua_isnumber(m_LuaState, a_StackPos))
|
if (!lua_isnumber(m_LuaState, a_StackPos))
|
||||||
{
|
{
|
||||||
a_ReturnedVal = static_cast<float>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
|
return false;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
a_ReturnedVal = static_cast<eBlockFace>(Clamp(
|
||||||
|
static_cast<int>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal)),
|
||||||
|
static_cast<int>(BLOCK_FACE_MIN), static_cast<int>(BLOCK_FACE_MAX))
|
||||||
|
);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -796,6 +819,46 @@ bool cLuaState::GetStackValue(int a_StackPos, eWeather & a_ReturnedVal)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cLuaState::GetStackValue(int a_StackPos, float & a_ReturnedVal)
|
||||||
|
{
|
||||||
|
if (lua_isnumber(m_LuaState, a_StackPos))
|
||||||
|
{
|
||||||
|
a_ReturnedVal = static_cast<float>(tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cLuaState::cStackValue cLuaState::WalkToValue(const AString & a_Name)
|
||||||
|
{
|
||||||
|
auto path = StringSplit(a_Name, ".");
|
||||||
|
lua_pushvalue(m_LuaState, -1); // Copy the stack value into the "working area"
|
||||||
|
for (const auto & elem: path)
|
||||||
|
{
|
||||||
|
// If the value is not a table, bail out (error):
|
||||||
|
if (!lua_istable(m_LuaState, -1))
|
||||||
|
{
|
||||||
|
lua_pop(m_LuaState, 1);
|
||||||
|
return cStackValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the next part of the path:
|
||||||
|
lua_getfield(m_LuaState, -1, elem.c_str());
|
||||||
|
|
||||||
|
// Remove the previous value from the stack (keep only the new one):
|
||||||
|
lua_remove(m_LuaState, -2);
|
||||||
|
} // for elem - path[]
|
||||||
|
return std::move(cStackValue(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cLuaState::CallFunction(int a_NumResults)
|
bool cLuaState::CallFunction(int a_NumResults)
|
||||||
{
|
{
|
||||||
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
|
ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
|
||||||
|
@ -78,11 +78,14 @@ public:
|
|||||||
bool IsValid(void) const {return (m_Ref != LUA_REFNIL); }
|
bool IsValid(void) const {return (m_Ref != LUA_REFNIL); }
|
||||||
|
|
||||||
/** Allows to use this class wherever an int (i. e. ref) is to be used */
|
/** Allows to use this class wherever an int (i. e. ref) is to be used */
|
||||||
operator int(void) const { return m_Ref; }
|
explicit operator int(void) const { return m_Ref; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
cLuaState * m_LuaState;
|
cLuaState * m_LuaState;
|
||||||
int m_Ref;
|
int m_Ref;
|
||||||
|
|
||||||
|
// Remove the copy-constructor:
|
||||||
|
cRef(const cRef &) = delete;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
@ -98,6 +101,12 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cTableRef(const cRef & a_TableRef, const char * a_FnName) :
|
||||||
|
m_TableRef(static_cast<int>(a_TableRef)),
|
||||||
|
m_FnName(a_FnName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int GetTableRef(void) const { return m_TableRef; }
|
int GetTableRef(void) const { return m_TableRef; }
|
||||||
const char * GetFnName(void) const { return m_FnName; }
|
const char * GetFnName(void) const { return m_FnName; }
|
||||||
} ;
|
} ;
|
||||||
@ -111,6 +120,61 @@ public:
|
|||||||
static const cRet Return; // Use this constant to delimit function args from return values for cLuaState::Call()
|
static const cRet Return; // Use this constant to delimit function args from return values for cLuaState::Call()
|
||||||
|
|
||||||
|
|
||||||
|
/** A RAII class for values pushed onto the Lua stack.
|
||||||
|
Will pop the value off the stack in the destructor. */
|
||||||
|
class cStackValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cStackValue(void):
|
||||||
|
m_LuaState(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
cStackValue(cLuaState & a_LuaState):
|
||||||
|
m_LuaState(a_LuaState)
|
||||||
|
{
|
||||||
|
m_StackLen = lua_gettop(a_LuaState);
|
||||||
|
}
|
||||||
|
|
||||||
|
cStackValue(cStackValue && a_Src):
|
||||||
|
m_LuaState(nullptr),
|
||||||
|
m_StackLen(-1)
|
||||||
|
{
|
||||||
|
std::swap(m_LuaState, a_Src.m_LuaState);
|
||||||
|
std::swap(m_StackLen, a_Src.m_StackLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
~cStackValue()
|
||||||
|
{
|
||||||
|
if (m_LuaState != nullptr)
|
||||||
|
{
|
||||||
|
auto top = lua_gettop(m_LuaState);
|
||||||
|
ASSERT(m_StackLen == top);
|
||||||
|
lua_pop(m_LuaState, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Set(cLuaState & a_LuaState)
|
||||||
|
{
|
||||||
|
m_LuaState = a_LuaState;
|
||||||
|
m_StackLen = lua_gettop(a_LuaState);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValid(void) const
|
||||||
|
{
|
||||||
|
return (m_LuaState != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
lua_State * m_LuaState;
|
||||||
|
|
||||||
|
int m_StackLen;
|
||||||
|
|
||||||
|
// Remove the copy-constructor:
|
||||||
|
cStackValue(const cStackValue &) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** Creates a new instance. The LuaState is not initialized.
|
/** Creates a new instance. The LuaState is not initialized.
|
||||||
a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins,
|
a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins,
|
||||||
or "LuaScript" for the cLuaScript template
|
or "LuaScript" for the cLuaScript template
|
||||||
@ -151,10 +215,9 @@ public:
|
|||||||
void AddPackagePath(const AString & a_PathVariable, const AString & a_Path);
|
void AddPackagePath(const AString & a_PathVariable, const AString & a_Path);
|
||||||
|
|
||||||
/** Loads the specified file
|
/** Loads the specified file
|
||||||
Returns false and logs a warning to the console if not successful (but the LuaState is kept open).
|
Returns false and optionally logs a warning to the console if not successful (but the LuaState is kept open).
|
||||||
m_SubsystemName is displayed in the warning log message.
|
m_SubsystemName is displayed in the warning log message. */
|
||||||
*/
|
bool LoadFile(const AString & a_FileName, bool a_LogWarnings = true);
|
||||||
bool LoadFile(const AString & a_FileName);
|
|
||||||
|
|
||||||
/** Returns true if a_FunctionName is a valid Lua function that can be called */
|
/** Returns true if a_FunctionName is a valid Lua function that can be called */
|
||||||
bool HasFunction(const char * a_FunctionName);
|
bool HasFunction(const char * a_FunctionName);
|
||||||
@ -169,6 +232,7 @@ public:
|
|||||||
void Push(const char * a_Value);
|
void Push(const char * a_Value);
|
||||||
void Push(const cItems & a_Items);
|
void Push(const cItems & a_Items);
|
||||||
void Push(const cPlayer * a_Player);
|
void Push(const cPlayer * a_Player);
|
||||||
|
void Push(const cRef & a_Ref);
|
||||||
void Push(const HTTPRequest * a_Request);
|
void Push(const HTTPRequest * a_Request);
|
||||||
void Push(const HTTPTemplateRequest * a_Request);
|
void Push(const HTTPTemplateRequest * a_Request);
|
||||||
void Push(const Vector3d & a_Vector);
|
void Push(const Vector3d & a_Vector);
|
||||||
@ -188,12 +252,13 @@ public:
|
|||||||
|
|
||||||
// GetStackValue() retrieves the value at a_StackPos, if it is a valid type. If not, a_Value is unchanged.
|
// GetStackValue() retrieves the value at a_StackPos, if it is a valid type. If not, a_Value is unchanged.
|
||||||
// Returns whether value was changed
|
// Returns whether value was changed
|
||||||
// Enum values are clamped to their allowed range.
|
// Enum values are checked for their allowed values and fail if the value is not assigned.
|
||||||
bool GetStackValue(int a_StackPos, AString & a_Value);
|
bool GetStackValue(int a_StackPos, AString & a_Value);
|
||||||
bool GetStackValue(int a_StackPos, bool & a_Value);
|
bool GetStackValue(int a_StackPos, bool & a_Value);
|
||||||
bool GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result);
|
bool GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result);
|
||||||
bool GetStackValue(int a_StackPos, cRef & a_Ref);
|
bool GetStackValue(int a_StackPos, cRef & a_Ref);
|
||||||
bool GetStackValue(int a_StackPos, double & a_Value);
|
bool GetStackValue(int a_StackPos, double & a_Value);
|
||||||
|
bool GetStackValue(int a_StackPos, eBlockFace & a_Value);
|
||||||
bool GetStackValue(int a_StackPos, eWeather & a_Value);
|
bool GetStackValue(int a_StackPos, eWeather & a_Value);
|
||||||
bool GetStackValue(int a_StackPos, float & a_ReturnedVal);
|
bool GetStackValue(int a_StackPos, float & a_ReturnedVal);
|
||||||
|
|
||||||
@ -202,21 +267,53 @@ public:
|
|||||||
bool GetStackValue(int a_StackPos, T & a_ReturnedVal, typename std::enable_if<std::is_integral<T>::value>::type * unused = nullptr)
|
bool GetStackValue(int a_StackPos, T & a_ReturnedVal, typename std::enable_if<std::is_integral<T>::value>::type * unused = nullptr)
|
||||||
{
|
{
|
||||||
UNUSED(unused);
|
UNUSED(unused);
|
||||||
if (lua_isnumber(m_LuaState, a_StackPos))
|
if (!lua_isnumber(m_LuaState, a_StackPos)) // Also accepts strings representing a number: http://pgl.yoyo.org/luai/i/lua_isnumber
|
||||||
{
|
{
|
||||||
lua_Number Val = tolua_tonumber(m_LuaState, a_StackPos, a_ReturnedVal);
|
return false;
|
||||||
if (Val > std::numeric_limits<T>::max())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (Val < std::numeric_limits<T>::min())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
a_ReturnedVal = static_cast<T>(Val);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
lua_Number Val = lua_tonumber(m_LuaState, a_StackPos);
|
||||||
|
if (Val > std::numeric_limits<T>::max())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Val < std::numeric_limits<T>::min())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
a_ReturnedVal = static_cast<T>(Val);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Pushes the named value in the table at the top of the stack.
|
||||||
|
a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue".
|
||||||
|
If the value is found, it is pushed on top of the stack and the returned cStackValue is valid.
|
||||||
|
If the value is not found, the stack is unchanged and the returned cStackValue is invalid. */
|
||||||
|
cStackValue WalkToValue(const AString & a_Name);
|
||||||
|
|
||||||
|
/** Retrieves the named value in the table at the top of the Lua stack.
|
||||||
|
a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue".
|
||||||
|
Returns true if the value was successfully retrieved, false on error. */
|
||||||
|
template <typename T> bool GetNamedValue(const AString & a_Name, T & a_Value)
|
||||||
|
{
|
||||||
|
auto stk = WalkToValue(a_Name);
|
||||||
|
if (!stk.IsValid())
|
||||||
|
{
|
||||||
|
// Name not found
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return GetStackValue(-1, a_Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Retrieves the named global value. a_Name may be a path containing multiple table levels, such as "_G.cChatColor.Blue".
|
||||||
|
Returns true if the value was successfully retrieved, false on error. */
|
||||||
|
template <typename T> bool GetNamedGlobal(const AString & a_Name, T & a_Value)
|
||||||
|
{
|
||||||
|
// Push the globals table onto the stack and make it RAII-removed:
|
||||||
|
lua_getglobal(m_LuaState, "_G");
|
||||||
|
cStackValue stk(*this);
|
||||||
|
|
||||||
|
// Get the named global:
|
||||||
|
return GetNamedValue(a_Name, a_Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include the auto-generated Push and GetStackValue() functions:
|
// Include the auto-generated Push and GetStackValue() functions:
|
||||||
@ -229,12 +326,12 @@ public:
|
|||||||
template <typename FnT, typename... Args>
|
template <typename FnT, typename... Args>
|
||||||
bool Call(const FnT & a_Function, Args &&... args)
|
bool Call(const FnT & a_Function, Args &&... args)
|
||||||
{
|
{
|
||||||
if (!PushFunction(a_Function))
|
if (!PushFunction(std::forward<const FnT &>(a_Function)))
|
||||||
{
|
{
|
||||||
// Pushing the function failed
|
// Pushing the function failed
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return PushCallPop(args...);
|
return PushCallPop(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Retrieves a list of values from the Lua stack, starting at the specified index. */
|
/** Retrieves a list of values from the Lua stack, starting at the specified index. */
|
||||||
@ -343,10 +440,10 @@ protected:
|
|||||||
|
|
||||||
/** Variadic template recursor: More params to push. Push them and recurse. */
|
/** Variadic template recursor: More params to push. Push them and recurse. */
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
inline bool PushCallPop(T a_Param, Args &&... args)
|
inline bool PushCallPop(T && a_Param, Args &&... args)
|
||||||
{
|
{
|
||||||
Push(a_Param);
|
Push(std::forward<T>(a_Param));
|
||||||
return PushCallPop(args...);
|
return PushCallPop(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Variadic template terminator: If there's nothing more to push, but return values to collect, call the function and collect the returns. */
|
/** Variadic template terminator: If there's nothing more to push, but return values to collect, call the function and collect the returns. */
|
||||||
@ -363,7 +460,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Collect the return values:
|
// Collect the return values:
|
||||||
GetStackValues(-NumReturns, args...);
|
GetStackValues(-NumReturns, std::forward<Args>(args)...);
|
||||||
lua_pop(m_LuaState, NumReturns);
|
lua_pop(m_LuaState, NumReturns);
|
||||||
|
|
||||||
// All successful:
|
// All successful:
|
||||||
|
@ -29,16 +29,16 @@ enum
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc
|
/** Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc */
|
||||||
enum eBlockFace
|
enum eBlockFace
|
||||||
{
|
{
|
||||||
BLOCK_FACE_NONE = -1, // Interacting with no block face - swinging the item in the air
|
BLOCK_FACE_NONE = -1, // Interacting with no block face - swinging the item in the air
|
||||||
BLOCK_FACE_XM = 4, // Interacting with the X- face of the block
|
BLOCK_FACE_XM = 4, // Interacting with the X- face of the block
|
||||||
BLOCK_FACE_XP = 5, // Interacting with the X+ face of the block
|
BLOCK_FACE_XP = 5, // Interacting with the X+ face of the block
|
||||||
BLOCK_FACE_YM = 0, // Interacting with the Y- face of the block
|
BLOCK_FACE_YM = 0, // Interacting with the Y- face of the block
|
||||||
BLOCK_FACE_YP = 1, // Interacting with the Y+ face of the block
|
BLOCK_FACE_YP = 1, // Interacting with the Y+ face of the block
|
||||||
BLOCK_FACE_ZM = 2, // Interacting with the Z- face of the block
|
BLOCK_FACE_ZM = 2, // Interacting with the Z- face of the block
|
||||||
BLOCK_FACE_ZP = 3, // Interacting with the Z+ face of the block
|
BLOCK_FACE_ZP = 3, // Interacting with the Z+ face of the block
|
||||||
|
|
||||||
// Synonyms using the (deprecated) world directions:
|
// Synonyms using the (deprecated) world directions:
|
||||||
BLOCK_FACE_BOTTOM = BLOCK_FACE_YM, // Interacting with the bottom face of the block
|
BLOCK_FACE_BOTTOM = BLOCK_FACE_YM, // Interacting with the bottom face of the block
|
||||||
@ -47,6 +47,10 @@ enum eBlockFace
|
|||||||
BLOCK_FACE_SOUTH = BLOCK_FACE_ZP, // Interacting with the southern face of the block
|
BLOCK_FACE_SOUTH = BLOCK_FACE_ZP, // Interacting with the southern face of the block
|
||||||
BLOCK_FACE_WEST = BLOCK_FACE_XM, // Interacting with the western face of the block
|
BLOCK_FACE_WEST = BLOCK_FACE_XM, // Interacting with the western face of the block
|
||||||
BLOCK_FACE_EAST = BLOCK_FACE_XP, // Interacting with the eastern face of the block
|
BLOCK_FACE_EAST = BLOCK_FACE_XP, // Interacting with the eastern face of the block
|
||||||
|
|
||||||
|
// Bounds, used for range-checking:
|
||||||
|
BLOCK_FACE_MIN = -1,
|
||||||
|
BLOCK_FACE_MAX = 5,
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user