35 #include "lua/src/lauxlib.h"
38 #include "../Defines.h"
39 #include "../FunctionRef.h"
40 #include "../Registries/CustomStatistics.h"
65 cStackBalanceCheck(
const char * a_FileName,
int a_LineNum, lua_State * a_LuaState,
bool a_ShouldLogStack =
true):
84 LOGD(
"Lua stack not balanced. Expected %d items, found %d items. Stack watching started in %s:%d",
89 ASSERT(!
"Lua stack unbalanced");
100 #define STRINGIFY2(X, Y) X##Y
101 #define STRINGIFY(X, Y) STRINGIFY2(X, Y)
102 #define ASSERT_LUA_STACK_BALANCE(...) cStackBalanceCheck STRINGIFY(Check, __COUNTER__)(__FILE__, __LINE__, __VA_ARGS__)
104 #define ASSERT_LUA_STACK_BALANCE(...)
115 m_Count(lua_gettop(a_LuaState))
131 LOGERROR(
"Unable to re-balance Lua stack, there are elements missing. Expected at least %d elements, got %d.",
m_Count, curTop);
132 throw std::runtime_error(fmt::format(FMT_STRING(
"Unable to re-balance Lua stack, there are elements missing. Expected at least {} elements, got {}."),
m_Count, curTop));
185 explicit operator int(
void)
const {
return m_Ref; }
194 a_LuaState.
Push(std::forward<T>(a_Object));
217 friend class ::cLuaState;
250 std::atomic<cCriticalSection *>
m_CS;
295 template <
typename... Args>
298 auto cs =
m_CS.load();
378 template <
typename... Args>
381 auto cs =
m_CS.load();
398 template <
typename... Args>
401 auto cs =
m_CS.load();
425 template <
typename T>
554 explicit cLuaState(lua_State * a_AttachState);
574 void Attach(lua_State * a_State);
603 template <
typename Arg1,
typename Arg2,
typename... Args>
604 void Push(Arg1 && a_Arg1, Arg2 && a_Arg2, Args &&... a_Args)
606 Push(std::forward<Arg1>(a_Arg1));
607 Push(std::forward<Arg2>(a_Arg2), std::forward<Args>(a_Args)...);
616 void Push(
const char * a_Value);
618 void Push(
const cNil & a_Nil);
619 void Push(
const cRef & a_Ref);
625 void Push(
bool a_Value);
631 void Push(
double a_Value);
632 void Push(
int a_Value);
633 void Push(
long a_Value);
635 void Push(std::chrono::milliseconds a_time);
638 void Pop(
int a_NumValuesToPop = 1);
650 bool GetStackValue(
int a_StackPos, cOptionalCallback & a_Callback);
667 bool GetStackValue(
int a_StackPos, std::string_view & a_Value);
670 template <
class T,
typename = std::enable_if_t<std::is_
integral_v<T>>>
677 lua_Number Val = lua_tonumber(
m_LuaState, a_StackPos);
678 if (Val > std::numeric_limits<T>::max())
682 if (Val < std::numeric_limits<T>::min())
686 a_ReturnedVal =
static_cast<T
>(Val);
691 template <
typename T>
702 template <
typename T>
750 template <
typename FnT,
typename... Args>
751 bool Call(
const FnT & a_Function, Args &&... args)
755 if (!
PushFunction(std::forward<const FnT &>(a_Function)))
760 auto res =
PushCallPop(std::forward<Args>(args)...);
765 template <
typename Arg1,
typename... Args>
768 if (!
GetStackValue(a_StartStackPos, std::forward<Arg1>(a_Arg1)))
772 return GetStackValues(a_StartStackPos + 1, std::forward<Args>(args)...);
779 bool CheckParamUserType(
int a_StartParam,
const char * a_UserType,
int a_EndParam = -1);
831 static bool ReportErrors(lua_State * a_LuaState,
int status);
837 static void LogStackTrace(lua_State * a_LuaState,
int a_StartingDepth = 0);
851 const AString & a_FunctionName,
862 int CopyStackFrom(
cLuaState & a_SrcLuaState,
int a_SrcStart,
int a_SrcEnd,
int a_NumAllowedNestingLevels = 16);
882 static void LogStackValues(lua_State * a_LuaState,
const char * a_Header =
nullptr);
930 template <
typename... Args>
949 template <
typename T,
typename... Args>
952 Push(std::forward<T>(a_Param));
958 template <
typename... Args>
962 int NumReturns =
sizeof...(args);
998 bool PushFunction(
const cRef & a_TableRef,
const char * a_FnName);
1021 void TrackRef(cTrackedRef & a_Ref);
1043 static void Add(
cLuaState & a_LuaState);
1046 static void Del(
cLuaState & a_LuaState);
1049 static AString GetStats(
void);
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
std::basic_string_view< std::byte > ContiguousByteBufferView
std::basic_string< std::byte > ContiguousByteBuffer
void LOGERROR(std::string_view a_Format, const Args &... args)
std::vector< AString > AStringVector
std::map< AString, AString > AStringMap
A string dictionary, used for key-value pairs.
Encapsulates a Lua state and provides some syntactic sugar for common operations.
void TrackRef(cTrackedRef &a_Ref)
Adds the specified reference to tracking.
bool CopyTableFrom(cLuaState &a_SrcLuaState, int a_TableIdx, int a_NumAllowedNestingLevels)
Copies a table at the specified stack index of the source Lua state to the top of this Lua state's st...
bool CheckParamFunction(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are functions; also logs warning if not.
bool PushFunction(const char *a_FunctionName)
Pushes the function of the specified name onto the stack.
void AddPackagePath(const AString &a_PathVariable, const AString &a_Path)
Adds the specified path to package.
bool CheckParamUserType(int a_StartParam, const char *a_UserType, int a_EndParam=-1)
Returns true if the specified parameters on the stack are of the specified usertype; also logs warnin...
bool CheckParamVector3(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are Vector3s; also logs warning if not.
std::vector< cTrackedRef * > m_TrackedRefs
The tracked references.
bool GetStackValues(int a_StartingStackPos)
Variadic template terminator: If there are no more values to get, bail out.
void Push(Arg1 &&a_Arg1, Arg2 &&a_Arg2, Args &&... a_Args)
Pushes multiple arguments onto the Lua stack.
bool GetStackValue(int a_StackPos, T &a_ReturnedVal)
void LogStackValues(const char *a_Header=nullptr)
Logs all the elements' types on the API stack, with an optional header for the listing.
cLuaState(const AString &a_SubsystemName)
Creates a new instance.
void LogStackTrace(int a_StartingDepth=0)
Logs all items in the current stack trace to the server console.
std::unique_ptr< cOptionalCallback > cOptionalCallbackPtr
bool GetStackValue(int a_StackPos, cOptionalParam< T > &&a_ReturnedVal)
Retrieves an optional value on the stack - doesn't fail if the stack contains nil instead of the valu...
std::unique_ptr< cCallback > cCallbackPtr
bool PushCallPop(cLuaState::cRet, Args &&... args)
Variadic template terminator: If there's nothing more to push, but return values to collect,...
bool PushCallPop(void)
Variadic template terminator: If there's nothing more to push / pop, just call the function.
bool ReportErrors(int status)
If the status is nonzero, prints the text on the top of Lua stack and returns true.
bool CheckParamEnd(int a_Param)
Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters)
cLuaState * QueryCanonLuaState(void) const
Returns the canon Lua state (the primary cLuaState instance that was used to create,...
bool IsParamUserType(int a_ParamIdx, const AString &a_UserType)
Returns true if the specified parameter is of the specified class.
bool CallFunction(int a_NumReturnValues)
Pushes a usertype of the specified class type onto the stack.
std::unique_ptr< cStackTable > cStackTablePtr
bool IsParamVector3(int a_ParamIdx)
Returns true if the specified parameter is any of the Vector3 types.
void ToString(int a_StackPos, AString &a_String)
Reads the value at the specified stack position as a string and sets it to a_String.
int CallFunctionWithForeignParams(const AString &a_FunctionName, cLuaState &a_SrcLuaState, int a_SrcParamStart, int a_SrcParamEnd)
Calls the function specified by its name, with arguments copied off the foreign state.
AString m_SubsystemName
The subsystem name is used for reporting errors to the console, it is either "plugin %s" or "LuaScrip...
bool CheckParamBool(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are bools; also logs warning if not.
void Close(void)
Closes the m_LuaState, if not closed already.
bool Call(const FnT &a_Function, Args &&... args)
Call the specified Lua function.
void UntrackRef(cTrackedRef &a_Ref)
Removes the specified reference from tracking.
static int BreakIntoDebugger(lua_State *a_LuaState)
Tries to break into the MobDebug debugger, if it is installed.
int m_NumCurrentFunctionArgs
Number of arguments currently pushed (for the Push / Call chain)
bool CheckParamSelf(const char *a_SelfClassName)
Returns true if the first parameter is an instance of the expected class name.
bool GetNamedValue(const AString &a_Name, T &a_Value)
Retrieves the named value in the table at the top of the Lua stack.
bool HasFunction(const char *a_FunctionName)
Returns true if a_FunctionName is a valid Lua function that can be called.
bool LoadFile(const AString &a_FileName, bool a_LogWarnings=true)
Loads the specified file Returns false and optionally logs a warning to the console if not successful...
bool CheckParamFunctionOrNil(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are functions or nils; also logs warning if not...
std::unique_ptr< cTrackedRef > cTrackedRefPtr
bool m_IsOwned
If true, the state is owned by this object and will be auto-Closed.
void RegisterAPILibs(void)
Registers all the API libraries that MCS provides into m_LuaState.
int CopyStackFrom(cLuaState &a_SrcLuaState, int a_SrcStart, int a_SrcEnd, int a_NumAllowedNestingLevels=16)
Copies objects on the stack from the specified state.
std::unique_ptr< cTableRef > cTableRefPtr
cStackValue WalkToNamedGlobal(const AString &a_Name)
Pushes the named value in the global table to the top of the stack.
bool CallTableFn(const cRef &a_TableRef, const char *a_FnName, Args &&... args)
Call the Lua function specified by name in the table stored as a reference.
bool IsValid(void) const
Returns true if the m_LuaState is valid.
std::shared_ptr< cTrackedRef > cTrackedRefSharedPtr
AString GetSubsystemName(void) const
Returns the name of the subsystem, as specified when the instance was created.
bool CheckParamString(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are strings; also logs warning if not.
bool CheckParamUserTable(int a_StartParam, const char *a_UserTable, int a_EndParam=-1)
Returns true if the specified parameters on the stack are of the specified usertable type; also logs ...
void LogApiCallParamFailure(const char *a_FnName, const char *a_ParamNames)
Outputs to log a warning about API call being unable to read its parameters from the stack,...
static int ReportFnCallErrors(lua_State *a_LuaState)
Used as the error reporting function for function calls.
bool GetNamedGlobal(const AString &a_Name, T &a_Value)
Retrieves the named global value.
AString m_CurrentFunctionName
Name of the currently pushed function (for the Push / Call chain)
bool CheckParamUUID(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are UUIDs; also logs warning if not Accepts eit...
bool CheckParamNumber(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are numbers; also logs warning if not.
cCriticalSection m_CSTrackedRefs
Protects m_TrackedRefs against multithreaded access.
AString GetTypeText(int a_StackPos)
Returns the type of the item on the specified position in the stack.
void UntrackInDeadlockDetect(cDeadlockDetect &a_DeadlockDetect)
Removes this object's CS from the DeadlockDetect's tracked CSs.
bool PushCallPop(T &&a_Param, Args &&... args)
Variadic template recursor: More params to push.
void Pop(int a_NumValuesToPop=1)
Pops the specified number of values off the top of the Lua stack.
cStackValue WalkToValue(const AString &a_Name)
Pushes the named value in the table at the top of the stack.
bool LoadString(const AString &a_StringToLoad, const AString &a_FileName, bool a_LogWarnings=true)
Loads the specified string.
void Detach(void)
Detaches a previously attached state.
bool CheckParamTable(int a_StartParam, int a_EndParam=-1)
Returns true if the specified parameters on the stack are tables; also logs warning if not.
bool CheckParamStaticSelf(const char *a_SelfClassName)
Returns true if the first parameter is the expected class (static).
bool GetStackValue(int a_StackPos, AString &a_Value)
int ApiParamError(std::string_view a_Msg)
Prints the message, prefixed with the current function name, then logs the stack contents and raises ...
void Attach(lua_State *a_State)
Attaches the specified state.
bool GetStackValues(int a_StartStackPos, Arg1 &&a_Arg1, Args &&... args)
Retrieves a list of values from the Lua stack, starting at the specified index.
bool CopySingleValueFrom(cLuaState &a_SrcLuaState, int a_StackIdx, int a_NumAllowedNestingLevels)
Copies a single value from the specified stack index of the source Lua state to the top of this Lua s...
void TrackInDeadlockDetect(cDeadlockDetect &a_DeadlockDetect)
Adds this object's CS to the DeadlockDetect's tracked CSs.
std::shared_ptr< cCallback > cCallbackSharedPtr
void Create(void)
Creates the m_LuaState, if not created already.
bool IsParamNumber(int a_ParamIdx)
Returns true if the specified parameter is a number.
Asserts that the Lua stack has the same amount of entries when this object is destructed,...
~cStackBalanceCheck() noexcept(false)
cStackBalanceCheck(const char *a_FileName, int a_LineNum, lua_State *a_LuaState, bool a_ShouldLogStack=true)
Makes sure that the Lua state's stack has the same number of elements on destruction as it had on con...
~cStackBalancePopper() noexcept(false)
cStackBalancePopper(cLuaState &a_LuaState)
Provides a RAII-style locking for the LuaState.
cLock(cLuaState &a_LuaState)
Used for storing references to object in the global registry.
void CreateFromObject(cLuaState &a_LuaState, T &&a_Object)
Creates a Lua reference to the specified object instance in the specified Lua state.
cRef(void)
Creates an unbound reference object.
void UnRef(void)
Removes the bound reference, resets the object to Unbound state.
bool IsValid(void) const
Returns true if the reference is valid.
cRef(const cRef &)=delete
lua_State * GetLuaState(void)
Returns the Lua state associated with the value.
void RefStack(cLuaState &a_LuaState, int a_StackPos)
Creates a reference to Lua object at the specified stack pos, binds this object to it.
Represents a reference to a Lua object that has a tracked lifetime -.
bool IsSameLuaState(cLuaState &a_LuaState)
Returns true if the reference resides in the specified Lua state.
cRef & GetRef()
Returns the internal reference.
cRef m_Ref
Reference to the Lua callback.
std::atomic< cCriticalSection * > m_CS
The mutex protecting m_Ref against multithreaded access.
cTrackedRef(cTrackedRef &&)=delete
This class cannot be moved, because it is tracked in the LuaState by-ptr.
cTrackedRef(void)
Creates an unbound ref instance.
cTrackedRef(const cTrackedRef &)=delete
This class cannot be copied, because it is tracked in the LuaState by-ptr.
bool IsValid(void)
Returns true if the contained reference is valid.
void Clear(void)
Frees the contained reference, if any.
bool RefStack(cLuaState &a_LuaState, int a_StackPos)
Set the contained reference to the object at the specified Lua state's stack position.
void Invalidate(void)
Invalidates the callback, without untracking it from the cLuaState.
Represents a stored callback to Lua that C++ code can call.
cCallback(const cCallback &)=delete
This class cannot be copied, because it is tracked in the LuaState by-ptr.
cCallback(cCallback &&)=delete
This class cannot be moved, because it is tracked in the LuaState by-ptr.
bool RefStack(cLuaState &a_LuaState, int a_StackPos)
Set the contained callback to the function in the specified Lua state's stack position.
bool Call(Args &&... args)
Calls the Lua callback, if still available.
Same thing as cCallback, but GetStackValue() won't fail if the callback value is nil.
bool RefStack(cLuaState &a_LuaState, int a_StackPos)
Set the contained callback to the function in the specified Lua state's stack position.
cOptionalCallback(const cOptionalCallback &)=delete
This class cannot be copied, because it is tracked in the LuaState by-ptr.
cOptionalCallback(cOptionalCallback &&)=delete
This class cannot be moved, because it is tracked in the LuaState by-ptr.
Represents a stored Lua table with callback functions that C++ code can call.
bool CallTableFnWithSelf(const char *a_FnName, Args &&... args)
Calls the Lua function stored under the specified name in the referenced table, if still available.
bool CallTableFn(const char *a_FnName, Args &&... args)
Calls the Lua function stored under the specified name in the referenced table, if still available.
bool RefStack(cLuaState &a_LuaState, int a_StackPos)
Set the contained reference to the table in the specified Lua state's stack position.
Represents a parameter that is optional - calling a GetStackValue() with this object will not fail if...
cOptionalParam(T &a_Dest)
A dummy class that's used only to delimit function args from return values for cLuaState::Call()
A dummy class that's used only to push a constant nil as a function parameter in Call().
A RAII class for values pushed onto the Lua stack.
int m_StackLen
Used for debugging, Lua state's stack size is checked against this number to make sure it is the same...
cStackValue(cLuaState &a_LuaState)
cStackValue(cStackValue &&a_Src)
cStackValue(const cStackValue &)=delete
void Set(cLuaState &a_LuaState)
~cStackValue() noexcept(false)
Represents a table on the Lua stack.
int m_StackPos
The stack index where the table resides in the Lua state.
cLuaState & m_LuaState
The Lua state in which the table resides.
cStackTable(cLuaState &a_LuaState, int a_StackPos)
cLuaState & GetLuaState(void) const
void ForEachArrayElement(cFunctionRef< bool(cLuaState &a_LuaState, int a_Index)> a_ElementCallback) const
Iterates over all array elements in the table consecutively and calls the a_ElementCallback for each.
void ForEachElement(cFunctionRef< bool(cLuaState &a_LuaState)> a_ElementCallback) const
Iterates over all dictionary elements in the table in random order, and calls the a_ElementCallback f...
Keeps track of all create cLuaState instances.
cLuaStatePtrs m_LuaStates
The internal list of LuaStates.
cCriticalSection m_CSLuaStates
Protects m_LuaStates against multithreaded access.
std::vector< cLuaStatePtr > cLuaStatePtrs
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.