diff --git a/SDK/src/NDK/Sdk.cpp b/SDK/src/NDK/Sdk.cpp index 3a45b65b3..21bfd236f 100644 --- a/SDK/src/NDK/Sdk.cpp +++ b/SDK/src/NDK/Sdk.cpp @@ -13,64 +13,80 @@ #include #include #include -#include #include -#include -#include -#include #include #include #include -#include #include -#include #include +#ifndef NDK_SERVER +#include +#include +#include +#include +#include +#include +#endif + namespace Ndk { bool Sdk::Initialize() { if (s_referenceCounter++ > 0) - return true; // Déjà initialisé + return true; // Already initialized try { Nz::ErrorFlags errFlags(Nz::ErrorFlag_ThrowException, true); - // Initialisation du moteur + // Initialize the engine first - // Modules clients - Nz::Audio::Initialize(); - Nz::Graphics::Initialize(); - - // Modules serveurs + // Shared modules Nz::Lua::Initialize(); Nz::Noise::Initialize(); Nz::Physics::Initialize(); Nz::Utility::Initialize(); - // Initialisation du SDK + #ifndef NDK_SERVER + // Client modules + Nz::Audio::Initialize(); + Nz::Graphics::Initialize(); + #endif - // Initialisation des composants et systèmes + // SDK Initialization + + // Components BaseComponent::Initialize(); - BaseSystem::Initialize(); - // Composants - InitializeComponent("NdkCam"); + // Shared components InitializeComponent("NdkColli"); - InitializeComponent("NdkLight"); - InitializeComponent("NdkList"); - InitializeComponent("NdkGfx"); InitializeComponent("NdkNode"); InitializeComponent("NdkPhys"); InitializeComponent("NdkVeloc"); - // Systèmes - InitializeSystem(); + #ifndef NDK_SERVER + // Client components + InitializeComponent("NdkCam"); + InitializeComponent("NdkLight"); + InitializeComponent("NdkList"); + InitializeComponent("NdkGfx"); + #endif + + // Systems + + BaseSystem::Initialize(); + + // Shared systems InitializeSystem(); - InitializeSystem(); InitializeSystem(); + #ifndef NDK_SERVER + // Client systems + InitializeSystem(); + InitializeSystem(); + #endif + NazaraNotice("Initialized: SDK"); return true; } @@ -86,23 +102,25 @@ namespace Ndk { if (s_referenceCounter != 1) { - // Le module est soit encore utilisé, soit pas initialisé + // Either the module is not initialized, either it was initialized multiple times if (s_referenceCounter > 1) s_referenceCounter--; return; } - // Libération du SDK + // Uninitialize the SDK s_referenceCounter = 0; - // Libération du moteur + // Uninitialize the engine - // Modules clients + #ifndef NDK_SERVER + // Client modules Nz::Audio::Uninitialize(); Nz::Graphics::Uninitialize(); + #endif - // Modules serveurs + // Shared modules Nz::Lua::Uninitialize(); Nz::Noise::Uninitialize(); Nz::Physics::Uninitialize(); diff --git a/SDK/src/NDK/World.cpp b/SDK/src/NDK/World.cpp index 92b3fa654..e8fff42f2 100644 --- a/SDK/src/NDK/World.cpp +++ b/SDK/src/NDK/World.cpp @@ -4,11 +4,14 @@ #include #include -#include #include -#include #include +#ifndef NDK_SERVER +#include +#include +#endif + namespace Ndk { World::~World() @@ -19,10 +22,13 @@ namespace Ndk void World::AddDefaultSystems() { - AddSystem(); AddSystem(); - AddSystem(); AddSystem(); + + #ifndef NDK_SERVER + AddSystem(); + AddSystem(); + #endif } const EntityHandle& World::CreateEntity() diff --git a/build/scripts/tools/ndk_server.lua b/build/scripts/tools/ndk_server.lua new file mode 100644 index 000000000..c94170dce --- /dev/null +++ b/build/scripts/tools/ndk_server.lua @@ -0,0 +1,40 @@ +TOOL.Name = "SDKServer" + +TOOL.Directory = "../SDK/lib" +TOOL.Kind = "Library" + +TOOL.Defines = { + "NDK_BUILD", + "NDK_SERVER" +} + +TOOL.Includes = { + "../SDK/include" +} + +TOOL.Files = { + "../SDK/include/NDK/**.hpp", + "../SDK/include/NDK/**.inl", + "../SDK/src/NDK/**.hpp", + "../SDK/src/NDK/**.inl", + "../SDK/src/NDK/**.cpp" +} + +-- Exlude client-only files +TOOL.FilesExclusion = { + "../SDK/**/CameraComponent.*", + "../SDK/**/GraphicsComponent.*", + "../SDK/**/LightComponent.*", + "../SDK/**/ListenerComponent.*", + "../SDK/**/ListenerSystem.*", + "../SDK/**/RenderSystem.*", + "../SDK/**/LuaInterface_Audio.*" +} + +TOOL.Libraries = { + "NazaraCore", + "NazaraLua", + "NazaraNoise", + "NazaraPhysics", + "NazaraUtility" +} diff --git a/include/Nazara/Core/Algorithm.hpp b/include/Nazara/Core/Algorithm.hpp index cbbd8af04..408eb79cf 100644 --- a/include/Nazara/Core/Algorithm.hpp +++ b/include/Nazara/Core/Algorithm.hpp @@ -25,6 +25,12 @@ namespace Nz template ByteArray ComputeHash(AbstractHash* hash, const T& v); template void HashCombine(std::size_t& seed, const T& v); + template + struct PointedType + { + using type = void; //< FIXME: I can't make SFINAE work + }; + template struct TypeTag {}; diff --git a/include/Nazara/Core/Algorithm.inl b/include/Nazara/Core/Algorithm.inl index 7c117e626..a23fea4e1 100644 --- a/include/Nazara/Core/Algorithm.inl +++ b/include/Nazara/Core/Algorithm.inl @@ -79,6 +79,11 @@ namespace Nz seed = static_cast(b * kMul); } + template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + template struct PointedType {typedef T type;}; + inline bool Serialize(SerializationContext& context, bool value) { if (context.currentBitPos == 8) diff --git a/include/Nazara/Core/ObjectRef.hpp b/include/Nazara/Core/ObjectRef.hpp index 0c82b3abc..8debb7d91 100644 --- a/include/Nazara/Core/ObjectRef.hpp +++ b/include/Nazara/Core/ObjectRef.hpp @@ -8,6 +8,7 @@ #define NAZARA_RESOURCEREF_HPP #include +#include #include #include @@ -44,6 +45,9 @@ namespace Nz private: T* m_object; }; + + template struct PointedType> {typedef T type;}; + template struct PointedType const> {typedef T type;}; } #include diff --git a/include/Nazara/Lua/LuaClass.hpp b/include/Nazara/Lua/LuaClass.hpp index fe592a4aa..7494dbe83 100644 --- a/include/Nazara/Lua/LuaClass.hpp +++ b/include/Nazara/Lua/LuaClass.hpp @@ -8,19 +8,22 @@ #define NAZARA_LUACLASS_HPP #include +#include #include #include #include #include #include -//#include +#include +#include namespace Nz { - template + template class LuaClass { - //static_assert(std::is_same::value || std::is_base_of::value, "P must be a base of T"); + template + friend class LuaClass; public: using ClassFunc = std::function; @@ -32,7 +35,8 @@ namespace Nz LuaClass(const String& name); - //void Inherit(LuaClass

& parent); + template + void Inherit(LuaClass

& parent); void Register(LuaInstance& lua); @@ -44,7 +48,8 @@ namespace Nz void SetMethod(const String& name, ClassFunc method); template std::enable_if_t::value> SetMethod(const String& name, R(P::*func)(Args...), DefArgs... defArgs); template std::enable_if_t::value> SetMethod(const String& name, R(P::*func)(Args...) const, DefArgs... defArgs); - void SetBindMode(LuaBindMode mode); + template std::enable_if_t::type>::value> SetMethod(const String& name, R(P::*func)(Args...), DefArgs... defArgs); + template std::enable_if_t::type>::value> SetMethod(const String& name, R(P::*func)(Args...) const, DefArgs... defArgs); void SetSetter(ClassIndexFunc setter); void SetStaticGetter(StaticIndexFunc getter); void SetStaticMethod(const String& name, StaticFunc func); @@ -52,9 +57,29 @@ namespace Nz void SetStaticSetter(StaticIndexFunc getter); private: + using ParentFunc = std::function; + using InstanceGetter = std::function; + + struct ClassInfo + { + std::vector methods; + std::vector parentGetters; + std::vector staticMethods; + std::unordered_map instanceGetters; + ClassIndexFunc getter; + ClassIndexFunc setter; + ConstructorFunc constructor; + FinalizerFunc finalizer; + StaticIndexFunc staticGetter; + StaticIndexFunc staticSetter; + String name; + int globalTableRef = -1; + }; + static int ConstructorProxy(lua_State* state); static int FinalizerProxy(lua_State* state); static int InfoDestructor(lua_State* state); + static void Get(const std::shared_ptr& info, LuaInstance& lua, T& instance); static int GetterProxy(lua_State* state); static int MethodProxy(lua_State* state); static int SetterProxy(lua_State* state); @@ -62,20 +87,6 @@ namespace Nz static int StaticMethodProxy(lua_State* state); static int StaticSetterProxy(lua_State* state); - struct ClassInfo - { - std::vector methods; - std::vector staticMethods; - ClassIndexFunc getter = nullptr; - ClassIndexFunc setter = nullptr; - ConstructorFunc constructor = nullptr; - FinalizerFunc finalizer = nullptr; - StaticIndexFunc staticGetter = nullptr; - StaticIndexFunc staticSetter = nullptr; - String name; - int globalTableRef = -1; - }; - std::map m_methods; std::map m_staticMethods; std::shared_ptr m_info; diff --git a/include/Nazara/Lua/LuaClass.inl b/include/Nazara/Lua/LuaClass.inl index 8f5a0bd21..5ca323a79 100644 --- a/include/Nazara/Lua/LuaClass.inl +++ b/include/Nazara/Lua/LuaClass.inl @@ -4,6 +4,7 @@ #include #include +#include #include namespace Nz @@ -14,15 +15,26 @@ namespace Nz { m_info->name = name; } - /* - template - void LuaClass::Inherit(LuaClass

& parent) - { - static_assert(std::is_base_of::value, "P must be a base of T"); - m_info->parentInfo = parent.m_info; + template + template + inline void LuaClass::Inherit(LuaClass

& parent) + { + static_assert(!std::is_same::value || std::is_base_of::value, "P must be a base of T"); + + std::shared_ptr::ClassInfo>& parentInfo = parent.m_info; + + parentInfo->instanceGetters[m_info->name] = [info = m_info](LuaInstance& lua) -> P* + { + return *static_cast(lua.CheckUserdata(1, info->name)); + }; + + m_info->parentGetters.emplace_back([parentInfo] (LuaInstance& lua, T& instance) + { + LuaClass

::Get(parentInfo, lua, instance); + }); } - */ + template void LuaClass::Register(LuaInstance& lua) { @@ -48,11 +60,16 @@ namespace Nz if (!lua.NewMetatable(m_info->name)) NazaraWarning("Class \"" + m_info->name + "\" already registred in this instance"); { - lua.PushValue(1); // On associe l'UserData avec la fonction - lua.PushCFunction(FinalizerProxy, 1); - lua.SetField("__gc"); // Finalizer + // Set the type in a __type field + lua.PushString(m_info->name); + lua.SetField("__type"); - if (m_info->getter) + // Define the Finalizer + lua.PushValue(1); + lua.PushCFunction(FinalizerProxy, 1); + lua.SetField("__gc"); + + if (m_info->getter || !m_info->parentGetters.empty()) { lua.PushValue(1); // shared_ptr on UserData lua.PushValue(-2); // Metatable @@ -76,14 +93,20 @@ namespace Nz m_info->methods.reserve(m_methods.size()); for (auto& pair : m_methods) { + std::size_t methodIndex = m_info->methods.size(); m_info->methods.push_back(pair.second); lua.PushValue(1); // shared_ptr on UserData - lua.PushInteger(m_info->methods.size() - 1); + lua.PushInteger(methodIndex); lua.PushCFunction(MethodProxy, 2); lua.SetField(pair.first); // Method name } + + m_info->instanceGetters[m_info->name] = [info = m_info](LuaInstance& lua) + { + return *static_cast(lua.CheckUserdata(1, info->name)); + }; } lua.Pop(); // On pop la metatable @@ -126,10 +149,11 @@ namespace Nz m_info->staticMethods.reserve(m_staticMethods.size()); for (auto& pair : m_staticMethods) { + std::size_t methodIndex = m_info->staticMethods.size(); m_info->staticMethods.push_back(pair.second); lua.PushValue(1); // shared_ptr on UserData - lua.PushInteger(m_info->staticMethods.size() - 1); + lua.PushInteger(methodIndex); lua.PushCFunction(StaticMethodProxy, 2); lua.SetField(pair.first); // ClassMeta.method = StaticMethodProxy @@ -181,7 +205,7 @@ namespace Nz { SetMethod(name, [func, defArgs...] (LuaInstance& instance, T& object) -> int { - LuaImplMethodProxy::Impl handler(instance, object, defArgs...); + typename LuaImplMethodProxy::template Impl handler(instance, object, defArgs...); handler.ProcessArgs(); return handler.Invoke(func); @@ -201,6 +225,32 @@ namespace Nz }); } + template + template + std::enable_if_t::type>::value> LuaClass::SetMethod(const String& name, R(P::*func)(Args...), DefArgs... defArgs) + { + SetMethod(name, [func, defArgs...](LuaInstance& instance, T& object) -> int + { + typename LuaImplMethodProxy::template Impl handler(instance, object, defArgs...); + handler.ProcessArgs(); + + return handler.Invoke(func); + }); + } + + template + template + std::enable_if_t::type>::value> LuaClass::SetMethod(const String& name, R(P::*func)(Args...) const, DefArgs... defArgs) + { + SetMethod(name, [func, defArgs...](LuaInstance& instance, T& object) -> int + { + typename LuaImplMethodProxy::template Impl handler(instance, object, defArgs...); + handler.ProcessArgs(); + + return handler.Invoke(func); + }); + } + template void LuaClass::SetSetter(ClassIndexFunc setter) { @@ -243,7 +293,7 @@ namespace Nz { LuaInstance& lua = *LuaInstance::GetInstance(state); - ClassInfo* info = *static_cast(lua.ToUserdata(lua.GetIndexOfUpValue(1))); + std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); const ConstructorFunc& constructor = info->constructor; lua.Remove(1); // On enlève l'argument "table" du stack @@ -255,10 +305,7 @@ namespace Nz return 0; // Normalement jamais exécuté (l'erreur provoquant une exception) } - T** ud = static_cast(lua.PushUserdata(sizeof(T*))); - *ud = instance; - lua.SetMetatable(info->name); - + lua.PushInstance(info->name.GetConstBuffer(), instance); return 1; } @@ -267,7 +314,7 @@ namespace Nz { LuaInstance& lua = *LuaInstance::GetInstance(state); - ClassInfo* info = *static_cast(lua.ToUserdata(lua.GetIndexOfUpValue(1))); + std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); const FinalizerFunc& finalizer = info->finalizer; T* instance = *static_cast(lua.CheckUserdata(1, info->name)); @@ -284,34 +331,54 @@ namespace Nz { LuaInstance& lua = *LuaInstance::GetInstance(state); - std::shared_ptr& infoPtr = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); - lua.DestroyReference(infoPtr->globalTableRef); + std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); + lua.DestroyReference(info->globalTableRef); using namespace std; // Obligatoire pour le destructeur - infoPtr.~shared_ptr(); // Si vous voyez une autre façon de faire, je suis preneur + info.~shared_ptr(); // Si vous voyez une autre façon de faire, je suis preneur return 0; } + template + void LuaClass::Get(const std::shared_ptr& info, LuaInstance& lua, T& instance) + { + const ClassIndexFunc& getter = info->getter; + + if (!getter || !getter(lua, instance)) + { + // Query from the metatable + lua.GetMetatable(info->name); //< Metatable + lua.PushValue(1); //< Field + lua.GetTable(); // Metatable[Field] + + lua.Remove(-2); // Remove Metatable + + if (!lua.IsValid(-1)) + { + for (const ParentFunc& getter : info->parentGetters) + { + lua.Pop(); //< Pop the last nil value + + getter(lua, instance); + if (lua.IsValid(-1)) + return; + } + } + } + } + template int LuaClass::GetterProxy(lua_State* state) { LuaInstance& lua = *LuaInstance::GetInstance(state); - ClassInfo* info = *static_cast(lua.ToUserdata(lua.GetIndexOfUpValue(1))); - const ClassIndexFunc& getter = info->getter; + std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); T& instance = *(*static_cast(lua.CheckUserdata(1, info->name))); lua.Remove(1); //< Remove the instance from the Lua stack - if (!getter(lua, instance)) - { - // On accède alors à la table - lua.PushValue(lua.GetIndexOfUpValue(2)); - lua.PushValue(-2); - lua.GetTable(); - } - + Get(info, lua, instance); return 1; } @@ -320,14 +387,26 @@ namespace Nz { LuaInstance& lua = *LuaInstance::GetInstance(state); - ClassInfo* info = *static_cast(lua.ToUserdata(lua.GetIndexOfUpValue(1))); - unsigned int index = static_cast(lua.ToInteger(lua.GetIndexOfUpValue(2))); - const ClassFunc& method = info->methods[index]; + std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); + + T* instance = nullptr; + if (lua.GetMetatable(1)) + { + LuaType type = lua.GetField("__type"); + if (type == LuaType_String) + { + String name = lua.ToString(-1); + auto it = info->instanceGetters.find(name); + if (it != info->instanceGetters.end()) + instance = it->second(lua); + } + } - T& instance = *(*static_cast(lua.CheckUserdata(1, info->name))); lua.Remove(1); //< Remove the instance from the Lua stack - return method(lua, instance); + unsigned int index = static_cast(lua.ToInteger(lua.GetIndexOfUpValue(2))); + const ClassFunc& method = info->methods[index]; + return method(lua, *instance); } template @@ -335,7 +414,7 @@ namespace Nz { LuaInstance& lua = *LuaInstance::GetInstance(state); - ClassInfo* info = *static_cast(lua.ToUserdata(lua.GetIndexOfUpValue(1))); + std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); const ClassIndexFunc& setter = info->setter; T& instance = *(*static_cast(lua.CheckUserdata(1, info->name))); @@ -357,7 +436,7 @@ namespace Nz { LuaInstance& lua = *LuaInstance::GetInstance(state); - ClassInfo* info = *static_cast(lua.ToUserdata(lua.GetIndexOfUpValue(1))); + std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); const StaticIndexFunc& getter = info->staticGetter; if (!getter(lua)) @@ -376,7 +455,7 @@ namespace Nz { LuaInstance& lua = *LuaInstance::GetInstance(state); - ClassInfo* info = *static_cast(lua.ToUserdata(lua.GetIndexOfUpValue(1))); + std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); unsigned int index = static_cast(lua.ToInteger(lua.GetIndexOfUpValue(2))); const StaticFunc& method = info->staticMethods[index]; @@ -388,7 +467,7 @@ namespace Nz { LuaInstance& lua = *LuaInstance::GetInstance(state); - ClassInfo* info = *static_cast(lua.ToUserdata(lua.GetIndexOfUpValue(1))); + std::shared_ptr& info = *static_cast*>(lua.ToUserdata(lua.GetIndexOfUpValue(1))); const StaticIndexFunc& setter = info->staticSetter; if (!setter(lua)) diff --git a/include/Nazara/Lua/LuaInstance.hpp b/include/Nazara/Lua/LuaInstance.hpp index b194bf11f..504a79254 100644 --- a/include/Nazara/Lua/LuaInstance.hpp +++ b/include/Nazara/Lua/LuaInstance.hpp @@ -117,6 +117,8 @@ namespace Nz void PushCFunction(LuaCFunction func, unsigned int upvalueCount = 0); void PushFunction(LuaFunction func); template void PushFunction(R(*func)(Args...), DefArgs... defArgs); + template void PushInstance(const char* tname, T* instance); + template void PushInstance(const char* tname, Args&&... args); void PushInteger(long long value); void PushLightUserdata(void* value); void PushMetatable(const char* str); diff --git a/include/Nazara/Lua/LuaInstance.inl b/include/Nazara/Lua/LuaInstance.inl index 20f568f64..47712161c 100644 --- a/include/Nazara/Lua/LuaInstance.inl +++ b/include/Nazara/Lua/LuaInstance.inl @@ -344,6 +344,32 @@ namespace Nz return LuaImplReplyVal(m_instance, std::move(Apply(m_object, func, m_args)), TypeTag()); } + template + std::enable_if_t::type>::value, int> Invoke(void(P::*func)(Args...)) + { + Apply(*m_object, func, m_args); + return 0; + } + + template + std::enable_if_t::type>::value, int> Invoke(Ret(P::*func)(Args...)) + { + return LuaImplReplyVal(m_instance, std::move(Apply(*m_object, func, m_args)), TypeTag()); + } + + template + std::enable_if_t::type>::value, int> Invoke(void(P::*func)(Args...) const) + { + Apply(*m_object, func, m_args); + return 0; + } + + template + std::enable_if_t::type>::value, int> Invoke(Ret(P::*func)(Args...) const) + { + return LuaImplReplyVal(m_instance, std::move(Apply(*m_object, func, m_args)), TypeTag()); + } + private: using ArgContainer = std::tuple>...>; using DefArgContainer = std::tuple>...>; @@ -404,4 +430,18 @@ namespace Nz return handler.Invoke(func); }); } + + template + void LuaInstance::PushInstance(const char* tname, T* instance) + { + T** userdata = static_cast(PushUserdata(sizeof(T*))); + *userdata = instance; + SetMetatable(tname); + } + + template + void LuaInstance::PushInstance(const char* tname, Args&&... args) + { + PushInstance(tname, new T(std::forward(args)...)); + } }