Cuberite
A lightweight, fast and extensible game server for Minecraft
LuaState.h
Go to the documentation of this file.
1 
2 // LuaState.h
3 
4 // Declares the cLuaState class representing the wrapper over lua_State *, provides associated helper functions
5 
6 /*
7 The contained lua_State can be either owned or attached.
8 Owned lua_State is created by calling Create() and the cLuaState automatically closes the state
9 Or, lua_State can be attached by calling Attach(), the cLuaState doesn't close such a state
10 If owning a state, trying to attach a state will automatically close the previously owned state.
11 
12 Calling a Lua function is done internally by pushing the function using PushFunction(), then pushing the
13 arguments and finally executing CallFunction(). cLuaState automatically keeps track of the number of
14 arguments and the name of the function (for logging purposes). After the call the return values are read from
15 the stack using GetStackValue(). All of this is wrapped in a templated function overloads cLuaState::Call().
16 
17 Reference management is provided by the cLuaState::cRef class. This is used when you need to hold a reference to
18 any Lua object across several function calls. The class is RAII-like, with automatic resource management. Note
19 that the cRef object is not inherently thread-safe and is not notified when its cLuaState is closed. For those
20 purposes, cTrackedRef can be used.
21 
22 Callbacks management is provided by the cLuaState::cCallback class. Use a GetStackValue() with cCallbackPtr
23 parameter to store the callback, and then at any time you can use the cCallback's Call() templated function
24 to call the callback. The callback management takes care of cLuaState being destroyed - the cCallback object
25 stays valid but doesn't call into Lua code anymore, returning false for "failure" instead.
26 */
27 
28 
29 
30 
31 #pragma once
32 
33 extern "C"
34 {
35  #include "lua/src/lauxlib.h"
36 }
37 
38 #include "../Defines.h"
39 #include "../FunctionRef.h"
40 #include "../Registries/CustomStatistics.h"
41 #include "PluginManager.h"
42 #include "LuaState_Typedefs.inc"
43 
44 // fwd:
45 class cLuaServerHandle;
46 class cLuaTCPLink;
47 class cLuaUDPEndpoint;
48 class cDeadlockDetect;
49 
50 
51 
52 
53 
55 class cLuaState
56 {
57 public:
58 
59  #ifndef NDEBUG
63  {
64  public:
65  cStackBalanceCheck(const char * a_FileName, int a_LineNum, lua_State * a_LuaState, bool a_ShouldLogStack = true):
66  m_FileName(a_FileName),
67  m_LineNum(a_LineNum),
68  m_LuaState(a_LuaState),
69  m_StackPos(lua_gettop(a_LuaState))
70  {
71  if (a_ShouldLogStack)
72  {
73  // DEBUG: If an unbalanced stack is reported, uncommenting the next line can help debug the imbalance
74  // cLuaState::LogStackValues(a_LuaState, fmt::format(FMT_STRING("Started checking Lua stack balance, currently {} items:"), m_StackPos).c_str());
75  // Since LogStackValues() itself uses the balance check, we must not call it recursively
76  }
77  }
78 
79  ~cStackBalanceCheck() noexcept(false)
80  {
81  auto currStackPos = lua_gettop(m_LuaState);
82  if (currStackPos != m_StackPos)
83  {
84  LOGD("Lua stack not balanced. Expected %d items, found %d items. Stack watching started in %s:%d",
85  m_StackPos, currStackPos,
86  m_FileName.c_str(), m_LineNum
87  );
89  ASSERT(!"Lua stack unbalanced"); // If this assert fires, the Lua stack is inbalanced, check the callstack / m_FileName / m_LineNum
90  }
91  }
92 
93  protected:
95  int m_LineNum;
96  lua_State * m_LuaState;
98  };
99 
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__)
103  #else
104  #define ASSERT_LUA_STACK_BALANCE(...)
105  #endif
106 
107 
111  {
112  public:
114  m_LuaState(a_LuaState),
115  m_Count(lua_gettop(a_LuaState))
116  {
117  }
118 
119  ~cStackBalancePopper() noexcept(false)
120  {
121  auto curTop = lua_gettop(m_LuaState);
122  if (curTop > m_Count)
123  {
124  // There are some leftover elements, adjust the stack:
125  m_LuaState.LogStackValues(fmt::format(FMT_STRING("Re-balancing Lua stack, expected {} values, got {}:"), m_Count, curTop).c_str());
126  lua_pop(m_LuaState, curTop - m_Count);
127  }
128  else if (curTop < m_Count)
129  {
130  // This is an irrecoverable error, rather than letting the Lua engine crash undefinedly later on, abort now:
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));
133  }
134  }
135 
136  protected:
138  int m_Count;
139  };
140 
141 
144  class cLock
145  {
146  public:
147  cLock(cLuaState & a_LuaState):
148  m_Lock(a_LuaState.m_CS)
149  {
150  }
151  protected:
153  };
154 
155 
159  class cRef
160  {
161  public:
163  cRef(void);
164 
166  cRef(cLuaState & a_LuaState, int a_StackPos);
167 
170  cRef(cRef && a_FromRef);
171 
172  ~cRef();
173 
176  void RefStack(cLuaState & a_LuaState, int a_StackPos);
177 
179  void UnRef(void);
180 
182  bool IsValid(void) const {return (m_Ref != LUA_REFNIL); }
183 
185  explicit operator int(void) const { return m_Ref; }
186 
188  lua_State * GetLuaState(void) { return m_LuaState; }
189 
192  template <typename T> void CreateFromObject(cLuaState & a_LuaState, T && a_Object)
193  {
194  a_LuaState.Push(std::forward<T>(a_Object));
195  RefStack(a_LuaState, -1);
196  a_LuaState.Pop();
197  }
198 
199  protected:
200  lua_State * m_LuaState;
201  int m_Ref;
202 
203  // Remove the copy-constructor:
204  cRef(const cRef &) = delete;
205  } ;
206 
207 
216  {
217  friend class ::cLuaState;
218  public:
220  cTrackedRef(void);
221 
223  {
224  Clear();
225  }
226 
229  bool RefStack(cLuaState & a_LuaState, int a_StackPos);
230 
233  void Clear(void);
234 
237  bool IsValid(void);
238 
242  bool IsSameLuaState(cLuaState & a_LuaState);
243 
244  protected:
245  friend class cLuaState;
246 
250  std::atomic<cCriticalSection *> m_CS;
251 
254 
255 
258  void Invalidate(void);
259 
262  cRef & GetRef() { return m_Ref; }
263 
266  cTrackedRef(const cTrackedRef &) = delete;
267 
270  cTrackedRef(cTrackedRef &&) = delete;
271  };
272  typedef std::unique_ptr<cTrackedRef> cTrackedRefPtr;
273  typedef std::shared_ptr<cTrackedRef> cTrackedRefSharedPtr;
274 
275 
283  class cCallback:
284  public cTrackedRef
285  {
287 
288  public:
289 
290  cCallback(void) {}
291 
295  template <typename... Args>
296  bool Call(Args &&... args)
297  {
298  auto cs = m_CS.load();
299  if (cs == nullptr)
300  {
301  return false;
302  }
303  cCSLock Lock(*cs);
304  if (!m_Ref.IsValid())
305  {
306  return false;
307  }
308  return cLuaState(m_Ref.GetLuaState()).Call(m_Ref, std::forward<Args>(args)...);
309  }
310 
314  bool RefStack(cLuaState & a_LuaState, int a_StackPos);
315 
316  protected:
317 
320  cCallback(const cCallback &) = delete;
321 
324  cCallback(cCallback &&) = delete;
325  };
326  typedef std::unique_ptr<cCallback> cCallbackPtr;
327  typedef std::shared_ptr<cCallback> cCallbackSharedPtr;
328 
329 
333  public cCallback
334  {
335  using Super = cCallback;
336 
337  public:
338 
340 
344  bool RefStack(cLuaState & a_LuaState, int a_StackPos);
345 
346  protected:
347 
351 
355  };
356  typedef std::unique_ptr<cOptionalCallback> cOptionalCallbackPtr;
357 
358 
367  class cTableRef:
368  public cTrackedRef
369  {
371 
372  public:
373  cTableRef(void) {}
374 
378  template <typename... Args>
379  bool CallTableFn(const char * a_FnName, Args &&... args)
380  {
381  auto cs = m_CS.load();
382  if (cs == nullptr)
383  {
384  return false;
385  }
386  cCSLock Lock(*cs);
387  if (!m_Ref.IsValid())
388  {
389  return false;
390  }
391  return cLuaState(m_Ref.GetLuaState()).CallTableFn(m_Ref, a_FnName, std::forward<Args>(args)...);
392  }
393 
398  template <typename... Args>
399  bool CallTableFnWithSelf(const char * a_FnName, Args &&... args)
400  {
401  auto cs = m_CS.load();
402  if (cs == nullptr)
403  {
404  return false;
405  }
406  cCSLock Lock(*cs);
407  if (!m_Ref.IsValid())
408  {
409  return false;
410  }
411  return cLuaState(m_Ref.GetLuaState()).CallTableFn(m_Ref, a_FnName, m_Ref, std::forward<Args>(args)...);
412  }
413 
417  bool RefStack(cLuaState & a_LuaState, int a_StackPos);
418  };
419  typedef std::unique_ptr<cTableRef> cTableRefPtr;
420 
421 
425  template <typename T>
427  {
428  public:
429  explicit cOptionalParam(T & a_Dest):
430  m_Dest(a_Dest)
431  {
432  }
433 
434  T & GetDest(void) { return m_Dest; }
435 
436  protected:
437  T & m_Dest;
438  };
439 
440 
442  class cRet
443  {
444  } ;
445  static const cRet Return; // Use this constant to delimit function args from return values for cLuaState::Call()
446 
447 
449  class cNil
450  {
451  };
452  static const cNil Nil; // Use this constant to give a function a nil parameter in Call()
453 
454 
458  {
459  public:
460  cStackValue(void):
461  m_LuaState(nullptr)
462  {
463  }
464 
465  cStackValue(cLuaState & a_LuaState):
466  m_LuaState(a_LuaState)
467  {
468  m_StackLen = lua_gettop(a_LuaState);
469  }
470 
472  m_LuaState(nullptr),
473  m_StackLen(-1)
474  {
475  std::swap(m_LuaState, a_Src.m_LuaState);
476  std::swap(m_StackLen, a_Src.m_StackLen);
477  }
478 
479  ~cStackValue() noexcept(false)
480  {
481  if (m_LuaState != nullptr)
482  {
483  ASSERT(m_StackLen == lua_gettop(m_LuaState));
484  lua_pop(m_LuaState, 1);
485  }
486  }
487 
488  void Set(cLuaState & a_LuaState)
489  {
490  m_LuaState = a_LuaState;
491  m_StackLen = lua_gettop(a_LuaState);
492  }
493 
494  bool IsValid(void) const
495  {
496  return (m_LuaState != nullptr);
497  }
498 
499  protected:
500  lua_State * m_LuaState;
501 
505 
506  // Remove the copy-constructor:
507  cStackValue(const cStackValue &) = delete;
508  };
509 
510 
516  {
517  public:
518  cStackTable(cLuaState & a_LuaState, int a_StackPos);
519 
524  void ForEachArrayElement(cFunctionRef<bool(cLuaState & a_LuaState, int a_Index)> a_ElementCallback) const;
525 
531  void ForEachElement(cFunctionRef<bool(cLuaState & a_LuaState)> a_ElementCallback) const;
532 
533  cLuaState & GetLuaState(void) const { return m_LuaState; }
534 
535  protected:
538 
541  };
542  typedef std::unique_ptr<cStackTable> cStackTablePtr;
543 
544 
549  cLuaState(const AString & a_SubsystemName);
550 
554  explicit cLuaState(lua_State * a_AttachState);
555 
556  ~cLuaState();
557 
559  operator lua_State * (void) { return m_LuaState; }
560 
565  void Create(void);
566 
568  void RegisterAPILibs(void);
569 
571  void Close(void);
572 
574  void Attach(lua_State * a_State);
575 
577  void Detach(void);
578 
580  bool IsValid(void) const { return (m_LuaState != nullptr); }
581 
583  AString GetSubsystemName(void) const { return m_SubsystemName; }
584 
586  void AddPackagePath(const AString & a_PathVariable, const AString & a_Path);
587 
591  bool LoadFile(const AString & a_FileName, bool a_LogWarnings = true);
592 
597  bool LoadString(const AString & a_StringToLoad, const AString & a_FileName, bool a_LogWarnings = true);
598 
600  bool HasFunction(const char * a_FunctionName);
601 
603  template <typename Arg1, typename Arg2, typename... Args>
604  void Push(Arg1 && a_Arg1, Arg2 && a_Arg2, Args &&... a_Args)
605  {
606  Push(std::forward<Arg1>(a_Arg1));
607  Push(std::forward<Arg2>(a_Arg2), std::forward<Args>(a_Args)...);
608  }
609 
610  // Push a const value onto the stack (keep alpha-sorted):
611  // Note that these functions will make a copy of the actual value, because Lua doesn't have the concept
612  // of "const", and there would be lifetime management problems if they didn't.
613  void Push(const AString & a_String);
614  void Push(const AStringMap & a_Dictionary);
615  void Push(const AStringVector & a_Vector);
616  void Push(const char * a_Value);
617  void Push(const cItem & a_Item);
618  void Push(const cNil & a_Nil);
619  void Push(const cRef & a_Ref);
620  void Push(ContiguousByteBufferView a_Data);
621  void Push(const Vector3d & a_Vector);
622  void Push(const Vector3i & a_Vector);
623 
624  // Push a simple value onto the stack (keep alpha-sorted):
625  void Push(bool a_Value);
626  void Push(cEntity * a_Entity);
627  void Push(const cEntity * a_Entity);
628  void Push(cLuaServerHandle * a_ServerHandle);
629  void Push(cLuaTCPLink * a_TCPLink);
630  void Push(cLuaUDPEndpoint * a_UDPEndpoint);
631  void Push(double a_Value);
632  void Push(int a_Value);
633  void Push(long a_Value);
634  void Push(const UInt32 a_Value);
635  void Push(std::chrono::milliseconds a_time);
636 
638  void Pop(int a_NumValuesToPop = 1);
639 
640  // GetStackValue() retrieves the value at a_StackPos, if it is a valid type. If not, a_Value is unchanged.
641  // Returns whether value was changed
642  // Enum values are checked for their allowed values and fail if the value is not assigned.
643  bool GetStackValue(int a_StackPos, AString & a_Value);
644  bool GetStackValue(int a_StackPos, AStringMap & a_Value);
645  bool GetStackValue(int a_StackPos, AStringVector & a_Value);
646  bool GetStackValue(int a_StackPos, bool & a_Value);
647  bool GetStackValue(int a_StackPos, cCallback & a_Callback);
648  bool GetStackValue(int a_StackPos, cCallbackPtr & a_Callback);
649  bool GetStackValue(int a_StackPos, cCallbackSharedPtr & a_Callback);
650  bool GetStackValue(int a_StackPos, cOptionalCallback & a_Callback);
651  bool GetStackValue(int a_StackPos, cOptionalCallbackPtr & a_Callback);
652  bool GetStackValue(int a_StackPos, cPluginManager::CommandResult & a_Result);
653  bool GetStackValue(int a_StackPos, cRef & a_Ref);
654  bool GetStackValue(int a_StackPos, cStackTablePtr & a_StackTable);
655  bool GetStackValue(int a_StackPos, cTableRef & a_TableRef);
656  bool GetStackValue(int a_StackPos, cTableRefPtr & a_TableRef);
657  bool GetStackValue(int a_StackPos, cTrackedRef & a_Ref);
658  bool GetStackValue(int a_StackPos, cTrackedRefPtr & a_Ref);
659  bool GetStackValue(int a_StackPos, cTrackedRefSharedPtr & a_Ref);
660  bool GetStackValue(int a_StackPos, ContiguousByteBuffer & a_Data);
661  bool GetStackValue(int a_StackPos, CustomStatistic & a_Value);
662  bool GetStackValue(int a_StackPos, double & a_Value);
663  bool GetStackValue(int a_StackPos, eBlockFace & a_Value);
664  bool GetStackValue(int a_StackPos, eWeather & a_Value);
665  bool GetStackValue(int a_StackPos, float & a_ReturnedVal);
666  bool GetStackValue(int a_StackPos, cUUID & a_Value);
667  bool GetStackValue(int a_StackPos, std::string_view & a_Value);
668 
669  // template to catch all of the various c++ integral types without overload conflicts
670  template <class T, typename = std::enable_if_t<std::is_integral_v<T>>>
671  bool GetStackValue(int a_StackPos, T & a_ReturnedVal)
672  {
673  if (!lua_isnumber(m_LuaState, a_StackPos)) // Also accepts strings representing a number: https://pgl.yoyo.org/luai/i/lua_isnumber
674  {
675  return false;
676  }
677  lua_Number Val = lua_tonumber(m_LuaState, a_StackPos);
678  if (Val > std::numeric_limits<T>::max())
679  {
680  return false;
681  }
682  if (Val < std::numeric_limits<T>::min())
683  {
684  return false;
685  }
686  a_ReturnedVal = static_cast<T>(Val);
687  return true;
688  }
689 
691  template <typename T>
692  bool GetStackValue(int a_StackPos, cOptionalParam<T> && a_ReturnedVal)
693  {
694  if (lua_isnoneornil(m_LuaState, a_StackPos))
695  {
696  return true;
697  }
698  return GetStackValue(a_StackPos, a_ReturnedVal.GetDest());
699  }
700 
702  template <typename T>
703  bool GetStackValue(int a_StackPos, Vector3<T> & a_ReturnedVal);
704 
709  cStackValue WalkToValue(const AString & a_Name);
710 
715  cStackValue WalkToNamedGlobal(const AString & a_Name);
716 
720  template <typename T> bool GetNamedValue(const AString & a_Name, T & a_Value)
721  {
722  auto stk = WalkToValue(a_Name);
723  if (!stk.IsValid())
724  {
725  // Name not found
726  return false;
727  }
728  return GetStackValue(-1, a_Value);
729  }
730 
733  template <typename T> bool GetNamedGlobal(const AString & a_Name, T & a_Value)
734  {
735  // Push the globals table onto the stack and make it RAII-removed:
736  lua_getglobal(m_LuaState, "_G");
737  cStackValue stk(*this);
738 
739  // Get the named global:
740  return GetNamedValue(a_Name, a_Value);
741  }
742 
743  // Include the auto-generated Push and GetStackValue() functions:
744  #include "LuaState_Declaration.inc"
745 
750  template <typename FnT, typename... Args>
751  bool Call(const FnT & a_Function, Args &&... args)
752  {
753  cStackBalancePopper balancer(*this);
755  if (!PushFunction(std::forward<const FnT &>(a_Function)))
756  {
757  // Pushing the function failed
758  return false;
759  }
760  auto res = PushCallPop(std::forward<Args>(args)...);
761  return res;
762  }
763 
765  template <typename Arg1, typename... Args>
766  inline bool GetStackValues(int a_StartStackPos, Arg1 && a_Arg1, Args &&... args)
767  {
768  if (!GetStackValue(a_StartStackPos, std::forward<Arg1>(a_Arg1)))
769  {
770  return false;
771  }
772  return GetStackValues(a_StartStackPos + 1, std::forward<Args>(args)...);
773  }
774 
776  bool CheckParamUserTable(int a_StartParam, const char * a_UserTable, int a_EndParam = -1);
777 
779  bool CheckParamUserType(int a_StartParam, const char * a_UserType, int a_EndParam = -1);
780 
782  bool CheckParamTable(int a_StartParam, int a_EndParam = -1);
783 
785  bool CheckParamNumber(int a_StartParam, int a_EndParam = -1);
786 
788  bool CheckParamBool(int a_StartParam, int a_EndParam = -1);
789 
791  bool CheckParamString(int a_StartParam, int a_EndParam = -1);
792 
794  bool CheckParamFunction(int a_StartParam, int a_EndParam = -1);
795 
797  bool CheckParamFunctionOrNil(int a_StartParam, int a_EndParam = -1);
798 
801  bool CheckParamUUID(int a_StartParam, int a_EndParam = -1);
802 
805  bool CheckParamVector3(int a_StartParam, int a_EndParam = -1);
806 
808  bool CheckParamEnd(int a_Param);
809 
812  bool CheckParamSelf(const char * a_SelfClassName);
813 
816  bool CheckParamStaticSelf(const char * a_SelfClassName);
817 
819  bool IsParamUserType(int a_ParamIdx, const AString & a_UserType);
820 
822  bool IsParamNumber(int a_ParamIdx);
823 
825  bool IsParamVector3(int a_ParamIdx);
826 
828  bool ReportErrors(int status);
829 
831  static bool ReportErrors(lua_State * a_LuaState, int status);
832 
834  void LogStackTrace(int a_StartingDepth = 0);
835 
837  static void LogStackTrace(lua_State * a_LuaState, int a_StartingDepth = 0);
838 
842  int ApiParamError(std::string_view a_Msg);
843 
845  AString GetTypeText(int a_StackPos);
846 
851  const AString & a_FunctionName,
852  cLuaState & a_SrcLuaState,
853  int a_SrcParamStart,
854  int a_SrcParamEnd
855  );
856 
862  int CopyStackFrom(cLuaState & a_SrcLuaState, int a_SrcStart, int a_SrcEnd, int a_NumAllowedNestingLevels = 16);
863 
868  bool CopyTableFrom(cLuaState & a_SrcLuaState, int a_TableIdx, int a_NumAllowedNestingLevels);
869 
873  bool CopySingleValueFrom(cLuaState & a_SrcLuaState, int a_StackIdx, int a_NumAllowedNestingLevels);
874 
876  void ToString(int a_StackPos, AString & a_String);
877 
879  void LogStackValues(const char * a_Header = nullptr);
880 
882  static void LogStackValues(lua_State * a_LuaState, const char * a_Header = nullptr);
883 
886  cLuaState * QueryCanonLuaState(void) const;
887 
890  void LogApiCallParamFailure(const char * a_FnName, const char * a_ParamNames);
891 
893  void TrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect);
894 
896  void UntrackInDeadlockDetect(cDeadlockDetect & a_DeadlockDetect);
897 
898 protected:
899 
901 
902  lua_State * m_LuaState;
903 
905  bool m_IsOwned;
906 
910 
913 
916 
920  std::vector<cTrackedRef *> m_TrackedRefs;
921 
924 
925 
930  template <typename... Args>
931  bool CallTableFn(const cRef & a_TableRef, const char * a_FnName, Args &&... args)
932  {
933  if (!PushFunction(a_TableRef, a_FnName))
934  {
935  // Pushing the function failed
936  return false;
937  }
938  return PushCallPop(std::forward<Args>(args)...);
939  }
940 
943  bool PushCallPop(void)
944  {
945  return CallFunction(0);
946  }
947 
949  template <typename T, typename... Args>
950  inline bool PushCallPop(T && a_Param, Args &&... args)
951  {
952  Push(std::forward<T>(a_Param));
954  return PushCallPop(std::forward<Args>(args)...);
955  }
956 
958  template <typename... Args>
959  bool PushCallPop(cLuaState::cRet, Args &&... args)
960  {
961  // Calculate the number of return values (number of args left):
962  int NumReturns = sizeof...(args);
963 
964  // Call the function:
965  if (!CallFunction(NumReturns))
966  {
967  return false;
968  }
969 
970  // Collect the return values:
971  GetStackValues(-NumReturns, std::forward<Args>(args)...);
972  lua_pop(m_LuaState, NumReturns);
973 
974  // All successful:
975  return true;
976  }
977 
981  bool GetStackValues(int a_StartingStackPos)
982  {
983  return true;
984  }
985 
989  bool PushFunction(const char * a_FunctionName);
990 
994  bool PushFunction(const cRef & a_FnRef);
995 
998  bool PushFunction(const cRef & a_TableRef, const char * a_FnName);
999 
1001  // void PushUserType(void * a_Object, const char * a_Type);
1002 
1011  bool CallFunction(int a_NumReturnValues);
1012 
1014  static int ReportFnCallErrors(lua_State * a_LuaState);
1015 
1017  static int BreakIntoDebugger(lua_State * a_LuaState);
1018 
1021  void TrackRef(cTrackedRef & a_Ref);
1022 
1025  void UntrackRef(cTrackedRef & a_Ref);
1026 }; // cLuaState
1027 
1028 // Instantiate the GetStackValue(Vector3<>) function for all Vector3 types:
1029 extern template bool cLuaState::GetStackValue(int a_StackPos, Vector3d & a_ReturnedVal);
1030 extern template bool cLuaState::GetStackValue(int a_StackPos, Vector3f & a_ReturnedVal);
1031 extern template bool cLuaState::GetStackValue(int a_StackPos, Vector3i & a_ReturnedVal);
1032 
1033 
1034 
1035 
1036 
1040 {
1041 public:
1043  static void Add(cLuaState & a_LuaState);
1044 
1046  static void Del(cLuaState & a_LuaState);
1047 
1049  static AString GetStats(void);
1050 
1051 protected:
1053  typedef std::vector<cLuaStatePtr> cLuaStatePtrs;
1054 
1058 
1061 
1062 
1064  static cLuaStateTracker & Get(void);
1065 };
1066 
1067 
1068 
1069 
eWeather
Definition: Defines.h:160
eBlockFace
Block face constants, used in PlayerDigging and PlayerBlockPlacement packets and bbox collision calc.
Definition: Defines.h:38
unsigned int UInt32
Definition: Globals.h:157
std::basic_string_view< std::byte > ContiguousByteBufferView
Definition: Globals.h:376
#define ASSERT(x)
Definition: Globals.h:276
std::basic_string< std::byte > ContiguousByteBuffer
Definition: Globals.h:375
void LOGERROR(std::string_view a_Format, const Args &... args)
Definition: LoggerSimple.h:73
#define LOGD
Definition: LoggerSimple.h:83
CustomStatistic
std::vector< AString > AStringVector
Definition: StringUtils.h:12
std::string AString
Definition: StringUtils.h:11
std::map< AString, AString > AStringMap
A string dictionary, used for key-value pairs.
Definition: StringUtils.h:16
Encapsulates a Lua state and provides some syntactic sugar for common operations.
Definition: LuaState.h:56
void TrackRef(cTrackedRef &a_Ref)
Adds the specified reference to tracking.
Definition: LuaState.cpp:2539
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...
Definition: LuaState.cpp:2280
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.
Definition: LuaState.cpp:1865
bool PushFunction(const char *a_FunctionName)
Pushes the function of the specified name onto the stack.
Definition: LuaState.cpp:728
void AddPackagePath(const AString &a_PathVariable, const AString &a_Path)
Adds the specified path to package.
Definition: LuaState.cpp:611
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...
Definition: LuaState.cpp:1694
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.
Definition: LuaState.cpp:1931
std::vector< cTrackedRef * > m_TrackedRefs
The tracked references.
Definition: LuaState.h:920
bool GetStackValues(int a_StartingStackPos)
Variadic template terminator: If there are no more values to get, bail out.
Definition: LuaState.h:981
void Push(Arg1 &&a_Arg1, Arg2 &&a_Arg2, Args &&... a_Args)
Pushes multiple arguments onto the Lua stack.
Definition: LuaState.h:604
bool GetStackValue(int a_StackPos, T &a_ReturnedVal)
Definition: LuaState.h:671
void LogStackValues(const char *a_Header=nullptr)
Logs all the elements' types on the API stack, with an optional header for the listing.
Definition: LuaState.cpp:2418
cLuaState(const AString &a_SubsystemName)
Creates a new instance.
Definition: LuaState.cpp:437
void LogStackTrace(int a_StartingDepth=0)
Logs all items in the current stack trace to the server console.
Definition: LuaState.cpp:2134
std::unique_ptr< cOptionalCallback > cOptionalCallbackPtr
Definition: LuaState.h:356
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...
Definition: LuaState.h:692
std::unique_ptr< cCallback > cCallbackPtr
Definition: LuaState.h:326
bool PushCallPop(cLuaState::cRet, Args &&... args)
Variadic template terminator: If there's nothing more to push, but return values to collect,...
Definition: LuaState.h:959
bool PushCallPop(void)
Variadic template terminator: If there's nothing more to push / pop, just call the function.
Definition: LuaState.h:943
bool ReportErrors(int status)
If the status is nonzero, prints the text on the top of Lua stack and returns true.
Definition: LuaState.cpp:2108
bool CheckParamEnd(int a_Param)
Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters)
Definition: LuaState.cpp:1998
cLuaState * QueryCanonLuaState(void) const
Returns the canon Lua state (the primary cLuaState instance that was used to create,...
Definition: LuaState.cpp:2467
cCriticalSection m_CS
Definition: LuaState.h:900
bool IsParamUserType(int a_ParamIdx, const AString &a_UserType)
Returns true if the specified parameter is of the specified class.
Definition: LuaState.cpp:2068
bool CallFunction(int a_NumReturnValues)
Pushes a usertype of the specified class type onto the stack.
Definition: LuaState.cpp:1623
std::unique_ptr< cStackTable > cStackTablePtr
Definition: LuaState.h:542
bool IsParamVector3(int a_ParamIdx)
Returns true if the specified parameter is any of the Vector3 types.
Definition: LuaState.cpp:2092
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.
Definition: LuaState.cpp:2404
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.
Definition: LuaState.cpp:2194
AString m_SubsystemName
The subsystem name is used for reporting errors to the console, it is either "plugin %s" or "LuaScrip...
Definition: LuaState.h:909
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.
Definition: LuaState.cpp:1796
void Close(void)
Closes the m_LuaState, if not closed already.
Definition: LuaState.cpp:529
bool Call(const FnT &a_Function, Args &&... args)
Call the specified Lua function.
Definition: LuaState.h:751
void UntrackRef(cTrackedRef &a_Ref)
Removes the specified reference from tracking.
Definition: LuaState.cpp:2558
static int BreakIntoDebugger(lua_State *a_LuaState)
Tries to break into the MobDebug debugger, if it is installed.
Definition: LuaState.cpp:2517
int m_NumCurrentFunctionArgs
Number of arguments currently pushed (for the Push / Call chain)
Definition: LuaState.h:915
bool CheckParamSelf(const char *a_SelfClassName)
Returns true if the first parameter is an instance of the expected class name.
Definition: LuaState.cpp:2018
bool GetNamedValue(const AString &a_Name, T &a_Value)
Retrieves the named value in the table at the top of the Lua stack.
Definition: LuaState.h:720
bool HasFunction(const char *a_FunctionName)
Returns true if a_FunctionName is a valid Lua function that can be called.
Definition: LuaState.cpp:709
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...
Definition: LuaState.cpp:637
static const cRet Return
Definition: LuaState.h:445
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...
Definition: LuaState.cpp:1898
std::unique_ptr< cTrackedRef > cTrackedRefPtr
Definition: LuaState.h:272
bool m_IsOwned
If true, the state is owned by this object and will be auto-Closed.
Definition: LuaState.h:905
void RegisterAPILibs(void)
Registers all the API libraries that MCS provides into m_LuaState.
Definition: LuaState.cpp:498
int CopyStackFrom(cLuaState &a_SrcLuaState, int a_SrcStart, int a_SrcEnd, int a_NumAllowedNestingLevels=16)
Copies objects on the stack from the specified state.
Definition: LuaState.cpp:2257
std::unique_ptr< cTableRef > cTableRefPtr
Definition: LuaState.h:419
cStackValue WalkToNamedGlobal(const AString &a_Name)
Pushes the named value in the global table to the top of the stack.
Definition: LuaState.cpp:1591
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.
Definition: LuaState.h:931
bool IsValid(void) const
Returns true if the m_LuaState is valid.
Definition: LuaState.h:580
std::shared_ptr< cTrackedRef > cTrackedRefSharedPtr
Definition: LuaState.h:273
AString GetSubsystemName(void) const
Returns the name of the subsystem, as specified when the instance was created.
Definition: LuaState.h:583
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.
Definition: LuaState.cpp:1829
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 ...
Definition: LuaState.cpp:1661
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,...
Definition: LuaState.cpp:2476
static int ReportFnCallErrors(lua_State *a_LuaState)
Used as the error reporting function for function calls.
Definition: LuaState.cpp:2505
bool GetNamedGlobal(const AString &a_Name, T &a_Value)
Retrieves the named global value.
Definition: LuaState.h:733
AString m_CurrentFunctionName
Name of the currently pushed function (for the Push / Call chain)
Definition: LuaState.h:912
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...
Definition: LuaState.cpp:1957
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.
Definition: LuaState.cpp:1763
cCriticalSection m_CSTrackedRefs
Protects m_TrackedRefs against multithreaded access.
Definition: LuaState.h:923
AString GetTypeText(int a_StackPos)
Returns the type of the item on the specified position in the stack.
Definition: LuaState.cpp:2185
void UntrackInDeadlockDetect(cDeadlockDetect &a_DeadlockDetect)
Removes this object's CS from the DeadlockDetect's tracked CSs.
Definition: LuaState.cpp:2496
bool PushCallPop(T &&a_Param, Args &&... args)
Variadic template recursor: More params to push.
Definition: LuaState.h:950
static const cNil Nil
Definition: LuaState.h:452
void Pop(int a_NumValuesToPop=1)
Pops the specified number of values off the top of the Lua stack.
Definition: LuaState.cpp:1108
cStackValue WalkToValue(const AString &a_Name)
Pushes the named value in the table at the top of the stack.
Definition: LuaState.cpp:1556
bool LoadString(const AString &a_StringToLoad, const AString &a_FileName, bool a_LogWarnings=true)
Loads the specified string.
Definition: LuaState.cpp:673
lua_State * m_LuaState
Definition: LuaState.h:902
void Detach(void)
Detaches a previously attached state.
Definition: LuaState.cpp:589
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.
Definition: LuaState.cpp:1727
bool CheckParamStaticSelf(const char *a_SelfClassName)
Returns true if the first parameter is the expected class (static).
Definition: LuaState.cpp:2043
bool GetStackValue(int a_StackPos, AString &a_Value)
Definition: LuaState.cpp:1119
int ApiParamError(std::string_view a_Msg)
Prints the message, prefixed with the current function name, then logs the stack contents and raises ...
Definition: LuaState.cpp:2161
void Attach(lua_State *a_State)
Attaches the specified state.
Definition: LuaState.cpp:567
bool GetStackValues(int a_StartStackPos, Arg1 &&a_Arg1, Args &&... args)
Retrieves a list of values from the Lua stack, starting at the specified index.
Definition: LuaState.h:766
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...
Definition: LuaState.cpp:2334
void TrackInDeadlockDetect(cDeadlockDetect &a_DeadlockDetect)
Adds this object's CS to the DeadlockDetect's tracked CSs.
Definition: LuaState.cpp:2487
std::shared_ptr< cCallback > cCallbackSharedPtr
Definition: LuaState.h:327
void Create(void)
Creates the m_LuaState, if not created already.
Definition: LuaState.cpp:480
bool IsParamNumber(int a_ParamIdx)
Returns true if the specified parameter is a number.
Definition: LuaState.cpp:2080
Asserts that the Lua stack has the same amount of entries when this object is destructed,...
Definition: LuaState.h:63
~cStackBalanceCheck() noexcept(false)
Definition: LuaState.h:79
cStackBalanceCheck(const char *a_FileName, int a_LineNum, lua_State *a_LuaState, bool a_ShouldLogStack=true)
Definition: LuaState.h:65
const AString m_FileName
Definition: LuaState.h:94
Makes sure that the Lua state's stack has the same number of elements on destruction as it had on con...
Definition: LuaState.h:111
~cStackBalancePopper() noexcept(false)
Definition: LuaState.h:119
cStackBalancePopper(cLuaState &a_LuaState)
Definition: LuaState.h:113
Provides a RAII-style locking for the LuaState.
Definition: LuaState.h:145
cLock(cLuaState &a_LuaState)
Definition: LuaState.h:147
cCSLock m_Lock
Definition: LuaState.h:152
Used for storing references to object in the global registry.
Definition: LuaState.h:160
void CreateFromObject(cLuaState &a_LuaState, T &&a_Object)
Creates a Lua reference to the specified object instance in the specified Lua state.
Definition: LuaState.h:192
cRef(void)
Creates an unbound reference object.
Definition: LuaState.cpp:2588
lua_State * m_LuaState
Definition: LuaState.h:200
void UnRef(void)
Removes the bound reference, resets the object to Unbound state.
Definition: LuaState.cpp:2650
bool IsValid(void) const
Returns true if the reference is valid.
Definition: LuaState.h:182
cRef(const cRef &)=delete
lua_State * GetLuaState(void)
Returns the Lua state associated with the value.
Definition: LuaState.h:188
void RefStack(cLuaState &a_LuaState, int a_StackPos)
Creates a reference to Lua object at the specified stack pos, binds this object to it.
Definition: LuaState.cpp:2633
Represents a reference to a Lua object that has a tracked lifetime -.
Definition: LuaState.h:216
bool IsSameLuaState(cLuaState &a_LuaState)
Returns true if the reference resides in the specified Lua state.
Definition: LuaState.cpp:268
cRef & GetRef()
Returns the internal reference.
Definition: LuaState.h:262
cRef m_Ref
Reference to the Lua callback.
Definition: LuaState.h:253
friend class cLuaState
Definition: LuaState.h:245
std::atomic< cCriticalSection * > m_CS
The mutex protecting m_Ref against multithreaded access.
Definition: LuaState.h:250
cTrackedRef(cTrackedRef &&)=delete
This class cannot be moved, because it is tracked in the LuaState by-ptr.
cTrackedRef(void)
Creates an unbound ref instance.
Definition: LuaState.cpp:194
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.
Definition: LuaState.cpp:253
void Clear(void)
Frees the contained reference, if any.
Definition: LuaState.cpp:222
bool RefStack(cLuaState &a_LuaState, int a_StackPos)
Set the contained reference to the object at the specified Lua state's stack position.
Definition: LuaState.cpp:203
void Invalidate(void)
Invalidates the callback, without untracking it from the cLuaState.
Definition: LuaState.cpp:292
Represents a stored callback to Lua that C++ code can call.
Definition: LuaState.h:285
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.
Definition: LuaState.cpp:319
bool Call(Args &&... args)
Calls the Lua callback, if still available.
Definition: LuaState.h:296
Same thing as cCallback, but GetStackValue() won't fail if the callback value is nil.
Definition: LuaState.h:334
bool RefStack(cLuaState &a_LuaState, int a_StackPos)
Set the contained callback to the function in the specified Lua state's stack position.
Definition: LuaState.cpp:337
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.
Definition: LuaState.h:369
bool CallTableFnWithSelf(const char *a_FnName, Args &&... args)
Calls the Lua function stored under the specified name in the referenced table, if still available.
Definition: LuaState.h:399
bool CallTableFn(const char *a_FnName, Args &&... args)
Calls the Lua function stored under the specified name in the referenced table, if still available.
Definition: LuaState.h:379
bool RefStack(cLuaState &a_LuaState, int a_StackPos)
Set the contained reference to the table in the specified Lua state's stack position.
Definition: LuaState.cpp:357
Represents a parameter that is optional - calling a GetStackValue() with this object will not fail if...
Definition: LuaState.h:427
cOptionalParam(T &a_Dest)
Definition: LuaState.h:429
A dummy class that's used only to delimit function args from return values for cLuaState::Call()
Definition: LuaState.h:443
A dummy class that's used only to push a constant nil as a function parameter in Call().
Definition: LuaState.h:450
A RAII class for values pushed onto the Lua stack.
Definition: LuaState.h:458
int m_StackLen
Used for debugging, Lua state's stack size is checked against this number to make sure it is the same...
Definition: LuaState.h:504
cStackValue(cLuaState &a_LuaState)
Definition: LuaState.h:465
cStackValue(cStackValue &&a_Src)
Definition: LuaState.h:471
cStackValue(const cStackValue &)=delete
void Set(cLuaState &a_LuaState)
Definition: LuaState.h:488
lua_State * m_LuaState
Definition: LuaState.h:500
~cStackValue() noexcept(false)
Definition: LuaState.h:479
bool IsValid(void) const
Definition: LuaState.h:494
Represents a table on the Lua stack.
Definition: LuaState.h:516
int m_StackPos
The stack index where the table resides in the Lua state.
Definition: LuaState.h:540
cLuaState & m_LuaState
The Lua state in which the table resides.
Definition: LuaState.h:537
cStackTable(cLuaState &a_LuaState, int a_StackPos)
Definition: LuaState.cpp:375
cLuaState & GetLuaState(void) const
Definition: LuaState.h:533
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.
Definition: LuaState.cpp:386
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...
Definition: LuaState.cpp:409
Keeps track of all create cLuaState instances.
Definition: LuaState.h:1040
cLuaStatePtrs m_LuaStates
The internal list of LuaStates.
Definition: LuaState.h:1057
cLuaState * cLuaStatePtr
Definition: LuaState.h:1052
cCriticalSection m_CSLuaStates
Protects m_LuaStates against multithreaded access.
Definition: LuaState.h:1060
std::vector< cLuaStatePtr > cLuaStatePtrs
Definition: LuaState.h:1053
Definition: Entity.h:76
Definition: Item.h:37
RAII for cCriticalSection - locks the CS on creation, unlocks on destruction.
Definition: UUID.h:11