diff options
author | LogicParrot <LogicParrot@users.noreply.github.com> | 2017-09-02 12:35:22 +0200 |
---|---|---|
committer | LogicParrot <LogicParrot@users.noreply.github.com> | 2017-09-02 12:35:22 +0200 |
commit | 07a5bf0984559d04fce1091b82b0952217ac64cc (patch) | |
tree | 0d1eee372a782213c9e2b84deaefe717b379a04b /src/Bindings | |
parent | Skeletons (diff) | |
parent | Revert "Replace ItemCallbacks with lambdas (#3948)" (diff) | |
download | cuberite-07a5bf0984559d04fce1091b82b0952217ac64cc.tar cuberite-07a5bf0984559d04fce1091b82b0952217ac64cc.tar.gz cuberite-07a5bf0984559d04fce1091b82b0952217ac64cc.tar.bz2 cuberite-07a5bf0984559d04fce1091b82b0952217ac64cc.tar.lz cuberite-07a5bf0984559d04fce1091b82b0952217ac64cc.tar.xz cuberite-07a5bf0984559d04fce1091b82b0952217ac64cc.tar.zst cuberite-07a5bf0984559d04fce1091b82b0952217ac64cc.zip |
Diffstat (limited to 'src/Bindings')
-rw-r--r-- | src/Bindings/LuaState.cpp | 2 | ||||
-rw-r--r-- | src/Bindings/LuaState.h | 2 | ||||
-rw-r--r-- | src/Bindings/LuaWindow.cpp | 15 | ||||
-rw-r--r-- | src/Bindings/LuaWindow.h | 5 | ||||
-rw-r--r-- | src/Bindings/ManualBindings.cpp | 68 | ||||
-rw-r--r-- | src/Bindings/ManualBindings.h | 235 | ||||
-rw-r--r-- | src/Bindings/ManualBindings_World.cpp | 6 | ||||
-rw-r--r-- | src/Bindings/PluginManager.cpp | 10 | ||||
-rw-r--r-- | src/Bindings/PluginManager.h | 11 |
9 files changed, 259 insertions, 95 deletions
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp index 57c420795..7bd4becb6 100644 --- a/src/Bindings/LuaState.cpp +++ b/src/Bindings/LuaState.cpp @@ -1,4 +1,4 @@ - + // LuaState.cpp // Implements the cLuaState class representing the wrapper over lua_State *, provides associated helper functions diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h index 2e82c6994..98f1cbc28 100644 --- a/src/Bindings/LuaState.h +++ b/src/Bindings/LuaState.h @@ -1,4 +1,4 @@ - + // LuaState.h // Declares the cLuaState class representing the wrapper over lua_State *, provides associated helper functions diff --git a/src/Bindings/LuaWindow.cpp b/src/Bindings/LuaWindow.cpp index ae390e576..2802c69db 100644 --- a/src/Bindings/LuaWindow.cpp +++ b/src/Bindings/LuaWindow.cpp @@ -54,15 +54,22 @@ cLuaWindow::~cLuaWindow() m_Contents.RemoveListener(*this); // Close open lua window from players, to avoid dangling pointers - cRoot::Get()->ForEachPlayer([this](cPlayer & a_Player) + class cPlayerCallback : public cPlayerListCallback + { + virtual bool Item(cPlayer * a_Player) { - if (a_Player.GetWindow() == this) + if (a_Player->GetWindow() == m_LuaWindow) { - a_Player.CloseWindow(false); + a_Player->CloseWindow(false); } return false; } - ); + cLuaWindow * m_LuaWindow; + public: + cPlayerCallback(cLuaWindow & a_LuaWindow) { m_LuaWindow = &a_LuaWindow; } + } PlayerCallback(*this); + + cRoot::Get()->ForEachPlayer(PlayerCallback); // Must delete slot areas now, because they are referencing this->m_Contents and would try to access it in cWindow's // destructor, when the member is already gone. diff --git a/src/Bindings/LuaWindow.h b/src/Bindings/LuaWindow.h index 31891c7a3..8f3349d00 100644 --- a/src/Bindings/LuaWindow.h +++ b/src/Bindings/LuaWindow.h @@ -1,4 +1,4 @@ - + // LuaWindow.h // Declares the cLuaWindow class representing a virtual window that plugins may create and open for the player @@ -9,14 +9,13 @@ #pragma once -#include <functional> #include "LuaState.h" #include "../UI/Window.h" #include "../ItemGrid.h" class cPlayer; -using cPlayerListCallback = std::function<bool(cPlayer &)>; +typedef cItemCallback<cPlayer> cPlayerListCallback; /** A window that has been created by a Lua plugin and is handled entirely by that plugin diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp index 5f8a3507d..38dc2cf83 100644 --- a/src/Bindings/ManualBindings.cpp +++ b/src/Bindings/ManualBindings.cpp @@ -1483,29 +1483,44 @@ static int tolua_cPluginManager_CallPlugin(lua_State * tolua_S) } // Call the destination plugin using a plugin callback: - int NumReturns = 0; - auto PluginCallback = [&](cPlugin & a_Plugin) + class cCallback : + public cPluginManager::cPluginCallback + { + public: + int m_NumReturns; + + cCallback(const AString & a_FunctionName, cLuaState & a_SrcLuaState) : + m_NumReturns(0), + m_FunctionName(a_FunctionName), + m_SrcLuaState(a_SrcLuaState) { - if (!a_Plugin.IsLoaded()) + } + protected: + const AString & m_FunctionName; + cLuaState & m_SrcLuaState; + + virtual bool Item(cPlugin * a_Plugin) override + { + if (!a_Plugin->IsLoaded()) { return false; } - NumReturns = static_cast<cPluginLua &>(a_Plugin).CallFunctionFromForeignState( - FunctionName, L, 4, lua_gettop(L) + m_NumReturns = static_cast<cPluginLua *>(a_Plugin)->CallFunctionFromForeignState( + m_FunctionName, m_SrcLuaState, 4, lua_gettop(m_SrcLuaState) ); return true; - }; - - if (!cPluginManager::Get()->DoWithPlugin(PluginName, PluginCallback)) + } + } Callback(FunctionName, L); + if (!cPluginManager::Get()->DoWithPlugin(PluginName, Callback)) { return 0; } - if (NumReturns < 0) + if (Callback.m_NumReturns < 0) { // The call has failed, there are zero return values. Do NOT return negative number (Lua considers that a "yield") return 0; } - return NumReturns; + return Callback.m_NumReturns; } @@ -3228,29 +3243,42 @@ static int tolua_cRoot_DoWithPlayerByUUID(lua_State * tolua_S) return 0; } + class cCallback : + public cPlayerListCallback + { + public: + cCallback(cLuaState & a_LuaState) : + m_LuaState(a_LuaState) + { + } + + virtual bool Item(cPlayer * a_Player) override + { + bool ret = false; + m_LuaState.Call(m_FnRef, a_Player, cLuaState::Return, ret); + return ret; + } + + cLuaState & m_LuaState; + cLuaState::cRef m_FnRef; + } Callback(L); + // Get parameters: cRoot * Self; cUUID PlayerUUID; - cLuaState::cRef FnRef; - L.GetStackValues(1, Self, PlayerUUID, FnRef); + L.GetStackValues(1, Self, PlayerUUID, Callback.m_FnRef); if (PlayerUUID.IsNil()) { return L.ApiParamError("Expected a non-nil UUID for parameter #1"); } - if (!FnRef.IsValid()) + if (!Callback.m_FnRef.IsValid()) { return L.ApiParamError("Expected a valid callback function for parameter #2"); } // Call the function: - bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer & a_Player) - { - bool ret = false; - L.Call(FnRef, &a_Player, cLuaState::Return, ret); - return ret; - } - ); + bool res = Self->DoWithPlayerByUUID(PlayerUUID, Callback); // Push the result as the return value: L.Push(res); diff --git a/src/Bindings/ManualBindings.h b/src/Bindings/ManualBindings.h index 64a44a240..dc9d9462f 100644 --- a/src/Bindings/ManualBindings.h +++ b/src/Bindings/ManualBindings.h @@ -1,4 +1,4 @@ - + // ManualBindings.h // Declares the cManualBindings class used as a namespace for functions exported to the Lua API manually @@ -57,7 +57,7 @@ public: template < class Ty1, class Ty2, - bool (Ty1::*DoWithFn)(const AString &, const std::function<bool(Ty2 &)> &) + bool (Ty1::*DoWithFn)(const AString &, cItemCallback<Ty2> &) > static int DoWith(lua_State * tolua_S) { @@ -89,14 +89,28 @@ public: return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2"); } - // Call the DoWith function: - bool res = (Self->*DoWithFn)(ItemName, [&](Ty2 & a_Item) + class cLuaCallback : public cItemCallback<Ty2> + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): + m_LuaState(a_LuaState), + m_FnRef(a_FnRef) + { + } + + private: + virtual bool Item(Ty2 * a_Item) override { bool ret = false; - L.Call(FnRef, &a_Item, cLuaState::Return, ret); + m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret); return ret; } - ); + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + } Callback(L, FnRef); + + // Call the DoWith function: + bool res = (Self->*DoWithFn)(ItemName, Callback); // Push the result as the return value: L.Push(res); @@ -111,7 +125,7 @@ public: template < class Ty1, class Ty2, - bool (Ty1::*DoWithFn)(const AString &, const std::function<bool(Ty2 &)> &) + bool (Ty1::*DoWithFn)(const AString &, cItemCallback<Ty2> &) > static int StaticDoWith(lua_State * tolua_S) { @@ -138,14 +152,28 @@ public: return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2"); } - // Call the DoWith function: - bool res = (Ty1::Get()->*DoWithFn)(ItemName, [&](Ty2 & a_Item) + class cLuaCallback : public cItemCallback<Ty2> + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): + m_LuaState(a_LuaState), + m_FnRef(a_FnRef) + { + } + + private: + virtual bool Item(Ty2 * a_Item) override { bool ret = false; - L.Call(FnRef, &a_Item, cLuaState::Return, ret); + m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret); return ret; } - ); + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + } Callback(L, FnRef); + + // Call the DoWith function: + bool res = (Ty1::Get()->*DoWithFn)(ItemName, Callback); // Push the result as the return value: L.Push(res); @@ -159,7 +187,7 @@ public: template < class Ty1, class Ty2, - bool (Ty1::*DoWithFn)(UInt32, const std::function<bool(Ty2 &)> &) + bool (Ty1::*DoWithFn)(UInt32, cItemCallback<Ty2> &) > static int DoWithID(lua_State * tolua_S) { @@ -187,14 +215,28 @@ public: return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2"); } - // Call the DoWith function: - bool res = (Self->*DoWithFn)(ItemID, [&](Ty2 & a_Item) + class cLuaCallback : public cItemCallback<Ty2> + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): + m_LuaState(a_LuaState), + m_FnRef(a_FnRef) + { + } + + private: + virtual bool Item(Ty2 * a_Item) override { bool ret = false; - L.Call(FnRef, &a_Item, cLuaState::Return, ret); + m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret); return ret; } - ); + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + } Callback(L, FnRef); + + // Call the DoWith function: + bool res = (Self->*DoWithFn)(ItemID, Callback); // Push the result as the return value: L.Push(res); @@ -209,7 +251,7 @@ public: template < class SELF, class ITEM, - bool (SELF::*DoWithFn)(int, int, int, const std::function<bool(ITEM &)> &) + bool (SELF::*DoWithFn)(int, int, int, cItemCallback<ITEM> &) > static int DoWithXYZ(lua_State * tolua_S) { @@ -240,14 +282,28 @@ public: return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #5"); } - // Call the DoWith function: - bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, [&](ITEM & a_Item) + class cLuaCallback : public cItemCallback<ITEM> + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): + m_LuaState(a_LuaState), + m_FnRef(a_FnRef) + { + } + + private: + virtual bool Item(ITEM * a_Item) override { bool ret = false; - L.Call(FnRef, &a_Item, cLuaState::Return, ret); + m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret); return ret; } - ); + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + } Callback(L, FnRef); + + // Call the DoWith function: + bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, Callback); // Push the result as the return value: L.Push(res); @@ -262,7 +318,7 @@ public: template < class SELF, class ITEM, - bool (SELF::*DoWithFn)(int, int, int, const std::function<bool(ITEM &)> &), + bool (SELF::*DoWithFn)(int, int, int, cItemCallback<ITEM> &), bool (SELF::*CoordCheckFn)(int, int, int) const > static int DoWithXYZ(lua_State * tolua_S) @@ -300,14 +356,28 @@ public: ).c_str()); } - // Call the DoWith function: - bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, [&](ITEM & a_Item) + class cLuaCallback : public cItemCallback<ITEM> + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): + m_LuaState(a_LuaState), + m_FnRef(a_FnRef) + { + } + + private: + virtual bool Item(ITEM * a_Item) override { bool ret = false; - L.Call(FnRef, &a_Item, cLuaState::Return, ret); + m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret); return ret; } - ); + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + } Callback(L, FnRef); + + // Call the DoWith function: + bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, Callback); // Push the result as the return value: L.Push(res); @@ -321,7 +391,7 @@ public: template < class Ty1, class Ty2, - bool (Ty1::*ForEachFn)(int, int, const std::function<bool(Ty2 &)> &) + bool (Ty1::*ForEachFn)(int, int, cItemCallback<Ty2> &) > static int ForEachInChunk(lua_State * tolua_S) { @@ -351,14 +421,28 @@ public: return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #4"); } - // Call the DoWith function: - bool res = (Self->*ForEachFn)(ChunkX, ChunkZ, [&](Ty2 & a_Item) + class cLuaCallback : public cItemCallback<Ty2> + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): + m_LuaState(a_LuaState), + m_FnRef(a_FnRef) + { + } + + private: + virtual bool Item(Ty2 * a_Item) override { bool ret = false; - L.Call(FnRef, &a_Item, cLuaState::Return, ret); + m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret); return ret; } - ); + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + } Callback(L, FnRef); + + // Call the DoWith function: + bool res = (Self->*ForEachFn)(ChunkX, ChunkZ, Callback); // Push the result as the return value: L.Push(res); @@ -372,7 +456,7 @@ public: template < class Ty1, class Ty2, - bool (Ty1::*ForEachFn)(const cBoundingBox &, const std::function<bool(Ty2 &)> &) + bool (Ty1::*ForEachFn)(const cBoundingBox &, cItemCallback<Ty2> &) > static int ForEachInBox(lua_State * tolua_S) { @@ -404,19 +488,36 @@ public: return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #2"); } - bool res = (Self->*ForEachFn)(*Box, [&](Ty2 & a_Item) + // Callback wrapper for the Lua function: + class cLuaCallback : public cItemCallback<Ty2> + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FuncRef) : + m_LuaState(a_LuaState), + m_FnRef(a_FuncRef) { - bool ret = false; - if (!L.Call(FnRef, &a_Item, cLuaState::Return, ret)) + } + + private: + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + + // cItemCallback<Ty2> overrides: + virtual bool Item(Ty2 * a_Item) override + { + bool res = false; + if (!m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res)) { LOGWARNING("Failed to call Lua callback"); - L.LogStackTrace(); + m_LuaState.LogStackTrace(); return true; // Abort enumeration } - return ret; + return res; } - ); + } Callback(L, FnRef); + + bool res = (Self->*ForEachFn)(*Box, Callback); // Push the result as the return value: L.Push(res); @@ -430,7 +531,7 @@ public: template < class Ty1, class Ty2, - bool (Ty1::*ForEachFn)(const std::function<bool(Ty2 &)> &) + bool (Ty1::*ForEachFn)(cItemCallback<Ty2> &) > static int ForEach(lua_State * tolua_S) { @@ -457,14 +558,29 @@ public: return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #1"); } - // Call the enumeration: - bool res = (Self->*ForEachFn)([&](Ty2 & a_Item) + class cLuaCallback : public cItemCallback<Ty2> + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): + m_LuaState(a_LuaState), + m_FnRef(a_FnRef) { - bool ret = false; // By default continue the enumeration - L.Call(FnRef, &a_Item, cLuaState::Return, ret); - return ret; } - ); + + private: + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + + virtual bool Item(Ty2 * a_Item) override + { + bool res = false; // By default continue the enumeration + m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res); + return res; + } + } Callback(L, FnRef); + + // Call the enumeration: + bool res = (Self->*ForEachFn)(Callback); // Push the return value: L.Push(res); @@ -479,7 +595,7 @@ public: template < class Ty1, class Ty2, - bool (Ty1::*ForEachFn)(const std::function<bool(Ty2 &)> &) + bool (Ty1::*ForEachFn)(cItemCallback<Ty2> &) > static int StaticForEach(lua_State * tolua_S) { @@ -500,14 +616,29 @@ public: return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #1"); } - // Call the enumeration: - bool res = (Ty1::Get()->*ForEachFn)([&](Ty2 & a_Item) + class cLuaCallback : public cItemCallback<Ty2> + { + public: + cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef): + m_LuaState(a_LuaState), + m_FnRef(a_FnRef) { - bool ret = false; // By default continue the enumeration - L.Call(FnRef, &a_Item, cLuaState::Return, ret); - return ret; } - ); + + private: + cLuaState & m_LuaState; + cLuaState::cRef & m_FnRef; + + virtual bool Item(Ty2 * a_Item) override + { + bool res = false; // By default continue the enumeration + m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, res); + return res; + } + } Callback(L, FnRef); + + // Call the enumeration: + bool res = (Ty1::Get()->*ForEachFn)(Callback); // Push the return value: L.Push(res); diff --git a/src/Bindings/ManualBindings_World.cpp b/src/Bindings/ManualBindings_World.cpp index 826439e3f..10b5daf1e 100644 --- a/src/Bindings/ManualBindings_World.cpp +++ b/src/Bindings/ManualBindings_World.cpp @@ -1,4 +1,4 @@ - + // ManualBindings_World.cpp // Implements the manual Lua API bindings for the cWorld class @@ -237,10 +237,10 @@ static int tolua_cWorld_DoWithPlayerByUUID(lua_State * tolua_S) } // Call the function: - bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer & a_Player) + bool res = Self->DoWithPlayerByUUID(PlayerUUID, [&](cPlayer * a_Player) { bool ret = false; - L.Call(FnRef, &a_Player, cLuaState::Return, ret); + L.Call(FnRef, a_Player, cLuaState::Return, ret); return ret; } ); diff --git a/src/Bindings/PluginManager.cpp b/src/Bindings/PluginManager.cpp index 1b3736e3c..7c4712f0f 100644 --- a/src/Bindings/PluginManager.cpp +++ b/src/Bindings/PluginManager.cpp @@ -1,4 +1,4 @@ - + #include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules #include "PluginManager.h" @@ -1993,14 +1993,14 @@ bool cPluginManager::IsValidHookType(int a_HookType) -bool cPluginManager::DoWithPlugin(const AString & a_PluginName, const cPluginCallback & a_Callback) +bool cPluginManager::DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback) { // TODO: Implement locking for plugins for (auto & plugin: m_Plugins) { if (plugin->GetName() == a_PluginName) { - return a_Callback(*plugin); + return a_Callback.Item(plugin.get()); } } return false; @@ -2010,12 +2010,12 @@ bool cPluginManager::DoWithPlugin(const AString & a_PluginName, const cPluginCal -bool cPluginManager::ForEachPlugin(const cPluginCallback & a_Callback) +bool cPluginManager::ForEachPlugin(cPluginCallback & a_Callback) { // TODO: Implement locking for plugins for (auto & plugin: m_Plugins) { - if (a_Callback(*plugin)) + if (a_Callback.Item(plugin.get())) { return false; } diff --git a/src/Bindings/PluginManager.h b/src/Bindings/PluginManager.h index 4de4bdeae..66f7d290a 100644 --- a/src/Bindings/PluginManager.h +++ b/src/Bindings/PluginManager.h @@ -1,9 +1,8 @@ - + #pragma once #include "Defines.h" -#include <functional> @@ -195,7 +194,7 @@ public: /** The interface used for enumerating and extern-calling plugins */ - using cPluginCallback = std::function<bool(cPlugin &)>; + typedef cItemCallback<cPlugin> cPluginCallback; typedef std::list<cPlugin *> PluginList; @@ -373,18 +372,18 @@ public: /** Calls the specified callback with the plugin object of the specified plugin. Returns false if plugin not found, otherwise returns the value that the callback has returned. */ - bool DoWithPlugin(const AString & a_PluginName, const cPluginCallback & a_Callback); + bool DoWithPlugin(const AString & a_PluginName, cPluginCallback & a_Callback); /** Calls the specified callback for each plugin in m_Plugins. Returns true if all plugins have been reported, false if the callback has aborted the enumeration by returning true. */ - bool ForEachPlugin(const cPluginCallback & a_Callback); + bool ForEachPlugin(cPluginCallback & a_Callback); /** Returns the name of the folder (cPlugin::GetFolderName()) from which the specified plugin was loaded. */ AString GetPluginFolderName(const AString & a_PluginName); // tolua_export /** Returns the path where individual plugins' folders are expected. The path doesn't end in a slash. */ - static AString GetPluginsPath(void) { return FILE_IO_PREFIX "Plugins"; } // tolua_export + static AString GetPluginsPath(void) { return FILE_IO_PREFIX + AString("Plugins"); } // tolua_export private: friend class cRoot; |