@@ -117,6 +117,8 @@ class LuaScriptRuntime : public OMClass<LuaScriptRuntime, IScriptRuntime, IScrip
117117
118118 int m_instanceId;
119119
120+ std::string m_nativesDir;
121+
120122public:
121123 inline LuaScriptRuntime ()
122124 {
@@ -169,6 +171,11 @@ class LuaScriptRuntime : public OMClass<LuaScriptRuntime, IScriptRuntime, IScrip
169171 return resourceName;
170172 }
171173
174+ inline std::string GetNativesDir ()
175+ {
176+ return m_nativesDir;
177+ }
178+
172179private:
173180 result_t LoadFileInternal (OMPtr<fxIStream> stream, char * scriptFile);
174181
@@ -180,6 +187,8 @@ class LuaScriptRuntime : public OMClass<LuaScriptRuntime, IScriptRuntime, IScrip
180187
181188 result_t LoadSystemFile (char * scriptFile);
182189
190+ result_t LoadNativesBuild (const std::string& nativeBuild);
191+
183192public:
184193 NS_DECL_ISCRIPTRUNTIME;
185194
@@ -940,6 +949,45 @@ int Lua_InvokeNative(lua_State* L)
940949 return numResults;
941950}
942951
952+ int Lua_LoadNative (lua_State* L)
953+ {
954+ const char * fn = luaL_checkstring (L, 1 );
955+
956+ auto runtime = LuaScriptRuntime::GetCurrent ();
957+
958+ OMPtr<fxIStream> stream;
959+
960+ result_t hr = runtime->GetScriptHost ()->OpenSystemFile (const_cast <char *>(va (" %s0x%08x.lua" , runtime->GetNativesDir (), HashRageString (fn))), stream.GetAddressOf ());
961+
962+ if (!FX_SUCCEEDED (hr))
963+ {
964+ lua_pushnil (L);
965+ return 1 ;
966+ }
967+
968+ // read file data
969+ uint64_t length;
970+
971+ if (FX_FAILED (hr = stream->GetLength (&length)))
972+ {
973+ lua_pushnil (L);
974+ return 1 ;
975+ }
976+
977+ std::vector<char > fileData (length + 1 );
978+ if (FX_FAILED (hr = stream->Read (&fileData[0 ], length, nullptr )))
979+ {
980+ lua_pushnil (L);
981+ return 1 ;
982+ }
983+
984+ fileData[length] = ' \0 ' ;
985+
986+ lua_pushlstring (L, fileData.data (), length);
987+
988+ return 1 ;
989+ }
990+
943991template <LuaMetaFields metaField>
944992int Lua_GetMetaField (lua_State* L)
945993{
@@ -998,6 +1046,7 @@ static const struct luaL_Reg g_citizenLib[] =
9981046 { " SetEventRoutine" , Lua_SetEventRoutine },
9991047 { " Trace" , Lua_Trace },
10001048 { " InvokeNative" , Lua_InvokeNative },
1049+ { " LoadNative" , Lua_LoadNative },
10011050 // ref things
10021051 { " SetCallRefRoutine" , Lua_SetCallRefRoutine },
10031052 { " SetDeleteRefRoutine" , Lua_SetDeleteRefRoutine },
@@ -1093,7 +1142,7 @@ result_t LuaScriptRuntime::Create(IScriptHost *scriptHost)
10931142 return hr;
10941143 }
10951144
1096- if (FX_FAILED (hr = LoadSystemFile ( const_cast < char *>( va ( " citizen:/scripting/lua/%s " , nativesBuild)) )))
1145+ if (FX_FAILED (hr = LoadNativesBuild ( nativesBuild)))
10971146 {
10981147 return hr;
10991148 }
@@ -1120,6 +1169,46 @@ result_t LuaScriptRuntime::Create(IScriptHost *scriptHost)
11201169 return FX_S_OK;
11211170}
11221171
1172+ result_t LuaScriptRuntime::LoadNativesBuild (const std::string& nativesBuild)
1173+ {
1174+ result_t hr = FX_S_OK;
1175+
1176+ bool useLazyNatives = false ;
1177+
1178+ #ifndef IS_FXSERVER
1179+ useLazyNatives = true ;
1180+
1181+ int32_t numFields = 0 ;
1182+
1183+ if (FX_SUCCEEDED (hr = m_resourceHost->GetNumResourceMetaData (" disable_lazy_natives" , &numFields)))
1184+ {
1185+ if (numFields > 0 )
1186+ {
1187+ useLazyNatives = false ;
1188+ }
1189+ }
1190+ #endif
1191+
1192+ if (!useLazyNatives)
1193+ {
1194+ if (FX_FAILED (hr = LoadSystemFile (const_cast <char *>(va (" citizen:/scripting/lua/%s" , nativesBuild)))))
1195+ {
1196+ return hr;
1197+ }
1198+ }
1199+ else
1200+ {
1201+ m_nativesDir = " nativesLua:/" + nativesBuild.substr (0 , nativesBuild.length () - 4 ) + " /" ;
1202+
1203+ if (FX_FAILED (hr = LoadSystemFile (const_cast <char *>(va (" citizen:/scripting/lua/%s" , " natives_loader.lua" )))))
1204+ {
1205+ return hr;
1206+ }
1207+ }
1208+
1209+ return FX_S_OK;
1210+ }
1211+
11231212result_t LuaScriptRuntime::Destroy ()
11241213{
11251214 // destroy any routines that may be referencing the Lua state
0 commit comments