Skip to content

Commit

Permalink
Added inspect() and iprint() scripting functions to help debugging
Browse files Browse the repository at this point in the history
string inspect ( arg, table options )  --Provides a human description of
any argument, i.e. string,bool,table,element,xml etc.   Options doc:
http://github.com/kikito/inspect.lua.
string iprint ( ... )  --Prints any number of arguments in human
readable format

Also cleaned up preloaded Lua code system for easier addition of
preloaded Lua in future.
  • Loading branch information
darkdreamingdan committed Jul 29, 2016
1 parent df8576f commit e8bf3b5
Show file tree
Hide file tree
Showing 9 changed files with 574 additions and 103 deletions.
5 changes: 5 additions & 0 deletions MTA10/mods/deathmatch/_Deathmatch 2008.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,11 @@
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\coroutine_debug.lua" />
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\exports.lua" />
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\inspect.lua" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
Expand Down
14 changes: 14 additions & 0 deletions MTA10/mods/deathmatch/_Deathmatch 2008.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
<Filter Include="Source Files\utils\lualib">
<UniqueIdentifier>{4ab2244d-178c-4ef0-856a-d8bc3800ebf7}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\shared\luascripts">
<UniqueIdentifier>{4e6bc0f9-67f1-4e13-a9e6-7478a8bf8a66}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CClient.cpp">
Expand Down Expand Up @@ -1694,4 +1697,15 @@
<Filter>Header Files\shared_logic\luadefs</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\coroutine_debug.lua">
<Filter>Source Files\shared\luascripts</Filter>
</None>
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\exports.lua">
<Filter>Source Files\shared\luascripts</Filter>
</None>
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\inspect.lua">
<Filter>Source Files\shared\luascripts</Filter>
</None>
</ItemGroup>
</Project>
65 changes: 13 additions & 52 deletions MTA10/mods/shared_logic/lua/CLuaMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,56 +27,8 @@ SString CLuaMain::ms_strExpectedUndumpHash;
#define HOOK_INSTRUCTION_COUNT 1000000
#define HOOK_MAXIMUM_TIME 5000


// This script is loaded into all VM's created.
const char szPreloadedScript [] = ""\

// Code for allowing this syntax: exports.resourceName:exportedFunctionName (...)
// exports["resourceName"]:exportedFunctionName (...)
// exports[resourcePointer]:exportedFunctionName (...)
// Aswell as the old: call ( getResourceFromName ( "resourceName" ), "exportedFunctionName", ... )
"local rescallMT = {}\n" \
"function rescallMT:__index(k)\n" \
" if type(k) ~= 'string' then k = tostring(k) end\n" \
" self[k] = function(resExportTable, ...)\n" \
" if type(self.res) == 'userdata' and getResourceRootElement(self.res) then\n" \
" return call(self.res, k, ...)\n" \
" else\n" \
" return nil\n" \
" end\n" \
" end\n" \
" return self[k]\n" \
"end\n" \
"local exportsMT = {}\n" \
"function exportsMT:__index(k)\n" \
" if type(k) == 'userdata' and getResourceRootElement(k) then\n" \
" return setmetatable({ res = k }, rescallMT)\n" \
" elseif type(k) ~= 'string' then\n" \
" k = tostring(k)\n" \
" end\n" \
" local res = getResourceFromName(k)\n" \
" if res then\n" \
" return setmetatable({ res = res }, rescallMT)\n" \
" else\n" \
" outputDebugString('exports: Call to non-running client resource (' .. k .. ')', 1)\n" \
" return setmetatable({}, rescallMT)\n" \
" end\n" \
"end\n" \
"exports = setmetatable({}, exportsMT)\n"

//
// Output errors that occur inside coroutines
//
"coroutine._resume = coroutine.resume\n" // For access to the original function
"local _coroutine_resume = coroutine.resume\n"
"function coroutine.resume(...)\n"
" local state,result = _coroutine_resume(...)\n"
" if not state then\n"
" outputDebugString( tostring(result), 1 )\n"
" end\n"
" return state,result\n"
"end\n"
;
SString SCRIPT_STACK = "";
char Luaify = 127;

CLuaMain::CLuaMain ( CLuaManager* pLuaManager, CResource* pResourceOwner, bool bEnableOOP )
{
Expand Down Expand Up @@ -879,9 +831,18 @@ void CLuaMain::InitVM ( void )
lua_pushelement ( m_luaVM, g_pClientGame->GetLocalPlayer() );
lua_setglobal ( m_luaVM, "localPlayer" );

// Load pre-loaded lua code
// Load pre-loaded lua scripts
DECLARE_PROFILER_SECTION( OnPreLoadScript )
LoadScript ( szPreloadedScript );
#include "luascripts/exports.lua"
LoadScript(SCRIPT_STACK);

#include "luascripts/coroutine_debug.lua"
LoadScript(SCRIPT_STACK);

#include "luascripts/inspect.lua"
LoadScript(SCRIPT_STACK);

SCRIPT_STACK.clear();
DECLARE_PROFILER_SECTION( OnPostLoadScript )
}

Expand Down
3 changes: 3 additions & 0 deletions MTA10_Server/mods/deathmatch/_ServerDeathmatch 2008.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1182,6 +1182,9 @@
<Xml Include="editor_acl.xml" />
</ItemGroup>
<ItemGroup>
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\coroutine_debug.lua" />
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\exports.lua" />
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\inspect.lua" />
<None Include="editor.conf" />
<None Include="local.conf" />
<None Include="Makefile.am" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@
<Filter Include="Resource Files\output">
<UniqueIdentifier>{4a26eed3-0f7c-400a-b106-efff6f2b1bb6}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\shared\luascripts">
<UniqueIdentifier>{00ed2c51-2063-4817-8c19-220d8d32275c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="CServer.cpp">
Expand Down Expand Up @@ -1923,5 +1926,14 @@
<None Include="..\..\output\README">
<Filter>Resource Files\output</Filter>
</None>
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\inspect.lua">
<Filter>Source Files\shared\luascripts</Filter>
</None>
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\coroutine_debug.lua">
<Filter>Source Files\shared\luascripts</Filter>
</None>
<None Include="..\..\..\Shared\mods\deathmatch\logic\luascripts\exports.lua">
<Filter>Source Files\shared\luascripts</Filter>
</None>
</ItemGroup>
</Project>
64 changes: 13 additions & 51 deletions MTA10_Server/mods/deathmatch/logic/lua/CLuaMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,55 +29,8 @@ SString CLuaMain::ms_strExpectedUndumpHash;
extern CGame* g_pGame;
extern CNetServer* g_pRealNetServer;

// This script is loaded into all VM's created.
const char szPreloadedScript [] = ""\

// Code for allowing this syntax: exports.resourceName:exportedFunctionName (...)
// exports["resourceName"]:exportedFunctionName (...)
// exports[resourcePointer]:exportedFunctionName (...)
// Aswell as the old: call ( getResourceFromName ( "resourceName" ), "exportedFunctionName", ... )
"local rescallMT = {}\n" \
"function rescallMT:__index(k)\n" \
" if type(k) ~= 'string' then k = tostring(k) end\n" \
" self[k] = function(resExportTable, ...)\n" \
" if type(self.res) == 'userdata' and getResourceRootElement(self.res) then\n" \
" return call(self.res, k, ...)\n" \
" else\n" \
" return nil\n" \
" end\n" \
" end\n" \
" return self[k]\n" \
"end\n" \
"local exportsMT = {}\n" \
"function exportsMT:__index(k)\n" \
" if type(k) == 'userdata' and getResourceRootElement(k) then\n" \
" return setmetatable({ res = k }, rescallMT)\n" \
" elseif type(k) ~= 'string' then\n" \
" k = tostring(k)\n" \
" end\n" \
" local res = getResourceFromName(k)\n" \
" if res and getResourceRootElement(res) then\n" \
" return setmetatable({ res = res }, rescallMT)\n" \
" else\n" \
" outputDebugString('exports: Call to non-running server resource (' .. k .. ')', 1)\n" \
" return setmetatable({}, rescallMT)\n" \
" end\n" \
"end\n" \
"exports = setmetatable({}, exportsMT)\n"

//
// Output errors that occur inside coroutines
//
"coroutine._resume = coroutine.resume\n" // For access to the original function
"local _coroutine_resume = coroutine.resume\n"
"function coroutine.resume(...)\n"
" local state,result = _coroutine_resume(...)\n"
" if not state then\n"
" outputDebugString( tostring(result), 1 )\n"
" end\n"
" return state,result\n"
"end\n"
;
SString SCRIPT_STACK = "";
char Luaify = 127;

CLuaMain::CLuaMain ( CLuaManager* pLuaManager,
CObjectManager* pObjectManager,
Expand Down Expand Up @@ -258,8 +211,17 @@ void CLuaMain::InitVM ( void )
lua_pushelement ( m_luaVM, m_pResource->GetResourceRootElement () );
lua_setglobal ( m_luaVM, "resourceRoot" );

// Load pre-loaded lua code
LoadScript ( szPreloadedScript );
// Load pre-loaded lua scripts
#include "luascripts/exports.lua"
LoadScript(SCRIPT_STACK);

#include "luascripts/coroutine_debug.lua"
LoadScript(SCRIPT_STACK);

#include "luascripts/inspect.lua"
LoadScript(SCRIPT_STACK);

SCRIPT_STACK.clear();
}


Expand Down
22 changes: 22 additions & 0 deletions Shared/mods/deathmatch/logic/luascripts/coroutine_debug.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--Luaify;SCRIPT_STACK=R"~LUACODE~(
--[[
SERVER AND CLIENT.
Output errors that occur inside coroutines
--]]

-- Protect some functions from modifications by resources
local tostring = tostring
local outputDebugString = outputDebugString

coroutine._resume = coroutine.resume -- For access to the original function
local _coroutine_resume = coroutine.resume
function coroutine.resume(...)
local state,result = _coroutine_resume(...)
if not state then
outputDebugString( tostring(result), 1 )
end
return state,result
end

--)~LUACODE~";
49 changes: 49 additions & 0 deletions Shared/mods/deathmatch/logic/luascripts/exports.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
--Luaify;SCRIPT_STACK=R"~LUACODE~(
--[[
SERVER AND CLIENT.
Code for allowing this syntax: exports.resourceName:exportedFunctionName (...)
exports["resourceName"]:exportedFunctionName (...)
exports[resourcePointer]:exportedFunctionName (...)
Aswell as the old: call ( getResourceFromName ( "resourceName" ), "exportedFunctionName", ... )
--]]

-- Protect some functions from modifications by resources
local getResourceRootElement = getResourceRootElement
local call = call
local getResourceFromName = getResourceFromName
local tostring = tostring
local outputDebugString = outputDebugString

local rescallMT = {}
function rescallMT:__index(k)
if type(k) ~= 'string' then k = tostring(k) end
self[k] = function(resExportTable, ...)
if type(self.res) == 'userdata' and getResourceRootElement(self.res) then
return call(self.res, k, ...)
else
return nil
end
end
return self[k]
end

local exportsMT = {}
function exportsMT:__index(k)
if type(k) == 'userdata' and getResourceRootElement(k) then
return setmetatable({ res = k }, rescallMT)
elseif type(k) ~= 'string' then
k = tostring(k)
end

local res = getResourceFromName(k)
if res and getResourceRootElement(res) then
return setmetatable({ res = res }, rescallMT)
else
outputDebugString('exports: Call to non-running server resource (' .. k .. ')', 1)
return setmetatable({}, rescallMT)
end
end
exports = setmetatable({}, exportsMT)

--)~LUACODE~";

3 comments on commit e8bf3b5

@jushar
Copy link
Contributor

@jushar jushar commented on e8bf3b5 Jul 29, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Luaify" is definitely an interesting approach, but in my humble opinion a bit too hacky for the little benefit we earn.

I'd suggest moving the Lua code into a namespace in .h files instead.

Like this:

namespace EmbeddedLuaCode
{
    const std::string Inspector = R"~LUA~(

local function isIdentifier(str)
    return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" )
end

    )~LUA~";
}

@darkdreamingdan
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your comment, was hoping to see opinions on this. I agree it's pretty hacky. The goal was to have .lua files that could come directly from a resource that could be loaded in transparently, or vice versa - let's say if someone wanted to improve inspect() for themself. This was never going to be entirely possible/practical - and 'Luaify' was the closest approach. I'm not opposed to your suggestion, but do think there's some do think there are advantages to making .lua files as simple as possible to load. Moving each .lua file into an individual .h file might prove a sensible middle ground (compared to the horrendous multiline C++03).

It's also worth considering the impact of dynamic allocation involved in 'Luaify' each time a new VM is created. I don't think it's significant but probably worth factoring into arguments against it.

Open to further comments surrounding this.

@darkdreamingdan
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering Premake, this hack becomes less attractive

Please sign in to comment.