summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--MCServer/.gitignore8
-rw-r--r--MCServer/Plugins/Debuggers/Debuggers.lua54
-rw-r--r--MCServer/webadmin/template.lua16
-rw-r--r--VC2008/MCServer.vcproj20
-rw-r--r--iniFile/iniFile.h5
-rw-r--r--source/AllToLua.pkg8
-rw-r--r--source/Bindings.cpp161
-rw-r--r--source/Bindings.h2
-rw-r--r--source/BlockEntities/ChestEntity.cpp2
-rw-r--r--source/BlockEntities/HopperEntity.cpp2
-rw-r--r--source/BlockTracer.h104
-rw-r--r--source/ChunkDef.h5
-rw-r--r--source/ChunkMap.cpp41
-rw-r--r--source/ChunkMap.h4
-rw-r--r--source/Item.h5
-rw-r--r--source/LineBlockTracer.cpp261
-rw-r--r--source/LineBlockTracer.h84
-rw-r--r--source/LuaScript.cpp235
-rw-r--r--source/LuaScript.h36
-rw-r--r--source/LuaState.cpp646
-rw-r--r--source/LuaState.h198
-rw-r--r--source/ManualBindings.cpp230
-rw-r--r--source/Plugin_NewLua.cpp750
-rw-r--r--source/Plugin_NewLua.h11
-rw-r--r--source/WebAdmin.cpp8
-rw-r--r--source/World.cpp66
-rw-r--r--source/World.h3
27 files changed, 2130 insertions, 835 deletions
diff --git a/MCServer/.gitignore b/MCServer/.gitignore
index 62225e137..ca10d90e8 100644
--- a/MCServer/.gitignore
+++ b/MCServer/.gitignore
@@ -1,11 +1,8 @@
*.exe
-ChunkWorx.ini
-ChunkWorxSave.ini
+*.ini
MCServer
-banned.ini
logs
players
-whitelist.ini
world*
API.txt
*.dat
@@ -15,9 +12,6 @@ schematics
*.pdb
memdump.xml
*.grab
-ProtectionAreas.ini
ProtectionAreas.sqlite
helgrind.log
-settings.ini
-webadmin.ini
motd.txt
diff --git a/MCServer/Plugins/Debuggers/Debuggers.lua b/MCServer/Plugins/Debuggers/Debuggers.lua
index f26b9a98d..e864cfe92 100644
--- a/MCServer/Plugins/Debuggers/Debuggers.lua
+++ b/MCServer/Plugins/Debuggers/Debuggers.lua
@@ -23,17 +23,18 @@ function Initialize(Plugin)
PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHAT);
PluginManager:AddHook(Plugin, cPluginManager.HOOK_PLAYER_RIGHT_CLICKING_ENTITY);
- PluginManager:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "Shows a list of all the loaded entities");
- PluginManager:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "Kills all the loaded entities");
- PluginManager:BindCommand("/wool", "debuggers", HandleWoolCmd, "Sets all your armor to blue wool");
- PluginManager:BindCommand("/testwnd", "debuggers", HandleTestWndCmd, "Opens up a window using plugin API");
- PluginManager:BindCommand("/gc", "debuggers", HandleGCCmd, "Activates the Lua garbage collector");
- PluginManager:BindCommand("/fast", "debuggers", HandleFastCmd, "Switches between fast and normal movement speed");
- PluginManager:BindCommand("/dash", "debuggers", HandleDashCmd, "Switches between fast and normal sprinting speed");
- PluginManager:BindCommand("/hunger", "debuggers", HandleHungerCmd, "Lists the current hunger-related variables");
- PluginManager:BindCommand("/poison", "debuggers", HandlePoisonCmd, "Sets food-poisoning for 15 seconds");
- PluginManager:BindCommand("/starve", "debuggers", HandleStarveCmd, "Sets the food level to zero");
- PluginManager:BindCommand("/fl", "debuggers", HandleFoodLevelCmd, "Sets the food level to the given value");
+ PluginManager:BindCommand("/le", "debuggers", HandleListEntitiesCmd, "- Shows a list of all the loaded entities");
+ PluginManager:BindCommand("/ke", "debuggers", HandleKillEntitiesCmd, "- Kills all the loaded entities");
+ PluginManager:BindCommand("/wool", "debuggers", HandleWoolCmd, "- Sets all your armor to blue wool");
+ PluginManager:BindCommand("/testwnd", "debuggers", HandleTestWndCmd, "- Opens up a window using plugin API");
+ PluginManager:BindCommand("/gc", "debuggers", HandleGCCmd, "- Activates the Lua garbage collector");
+ PluginManager:BindCommand("/fast", "debuggers", HandleFastCmd, "- Switches between fast and normal movement speed");
+ PluginManager:BindCommand("/dash", "debuggers", HandleDashCmd, "- Switches between fast and normal sprinting speed");
+ PluginManager:BindCommand("/hunger", "debuggers", HandleHungerCmd, "- Lists the current hunger-related variables");
+ PluginManager:BindCommand("/poison", "debuggers", HandlePoisonCmd, "- Sets food-poisoning for 15 seconds");
+ PluginManager:BindCommand("/starve", "debuggers", HandleStarveCmd, "- Sets the food level to zero");
+ PluginManager:BindCommand("/fl", "debuggers", HandleFoodLevelCmd, "- Sets the food level to the given value");
+ PluginManager:BindCommand("/spidey", "debuggers", HandleSpideyCmd, "- Shoots a line of web blocks until it hits non-air");
-- Enable the following line for BlockArea / Generator interface testing:
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
@@ -707,3 +708,34 @@ end
+
+function HandleSpideyCmd(a_Split, a_Player)
+ -- Place a line of cobwebs from the player's eyes until non-air block, in the line-of-sight of the player
+ local World = a_Player:GetWorld();
+
+ local Callbacks = {
+ OnNextBlock = function(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta)
+ if (a_BlockType ~= E_BLOCK_AIR) then
+ -- abort the trace
+ return true;
+ end
+ World:SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_COBWEB, 0);
+ end
+ };
+
+ local EyePos = a_Player:GetEyePosition();
+ local LookVector = a_Player:GetLookVector();
+ LookVector:Normalize();
+
+ -- Start cca 2 blocks away from the eyes
+ local Start = EyePos + LookVector + LookVector;
+ local End = EyePos + LookVector * 50;
+
+ cLineBlockTracer.Trace(World, Callbacks, Start.x, Start.y, Start.z, End.x, End.y, End.z);
+
+ return true;
+end
+
+
+
+
diff --git a/MCServer/webadmin/template.lua b/MCServer/webadmin/template.lua
index f508ad5aa..1ab1aab88 100644
--- a/MCServer/webadmin/template.lua
+++ b/MCServer/webadmin/template.lua
@@ -4,6 +4,10 @@ function Output(String)
table.insert(SiteContent, String)
end
+
+
+
+
function GetTableSize(Table)
local Size = 0
for key,value in pairs(Table) do
@@ -12,6 +16,10 @@ function GetTableSize(Table)
return Size
end
+
+
+
+
function GetDefaultPage()
local PM = cRoot:Get():GetPluginManager()
@@ -42,11 +50,15 @@ function GetDefaultPage()
return Content, SubTitle
end
+
+
+
+
function ShowPage(WebAdmin, TemplateRequest)
SiteContent = {}
local BaseURL = WebAdmin:GetBaseURL(TemplateRequest.Request.Path)
local Title = "MCServer"
- local MemoryUsage = WebAdmin:GetMemoryUsage()
+ local MemoryUsage = cWebAdmin:GetMemoryUsage()
local NumChunks = cRoot:Get():GetTotalChunkCount()
local PluginPage = WebAdmin:GetPage(TemplateRequest.Request)
local PageContent = PluginPage.Content
@@ -408,6 +420,7 @@ function ShowPage(WebAdmin, TemplateRequest)
<div id="sidebar">
<ul class="sideNav">
]])
+
local AllPlugins = WebAdmin:GetPlugins()
for key,value in pairs(AllPlugins) do
@@ -421,6 +434,7 @@ function ShowPage(WebAdmin, TemplateRequest)
end
end
end
+
Output([[
</ul>
diff --git a/VC2008/MCServer.vcproj b/VC2008/MCServer.vcproj
index dc0291cd6..591ee678a 100644
--- a/VC2008/MCServer.vcproj
+++ b/VC2008/MCServer.vcproj
@@ -307,6 +307,10 @@
>
</File>
<File
+ RelativePath="..\source\BlockTracer.h"
+ >
+ </File>
+ <File
RelativePath="..\source\ByteBuffer.cpp"
>
</File>
@@ -546,6 +550,14 @@
>
</File>
<File
+ RelativePath="..\source\LineBlockTracer.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\source\LineBlockTracer.h"
+ >
+ </File>
+ <File
RelativePath="..\source\Log.cpp"
>
</File>
@@ -1486,6 +1498,14 @@
>
</File>
<File
+ RelativePath="..\source\LuaState.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\source\LuaState.h"
+ >
+ </File>
+ <File
RelativePath="..\source\LuaWindow.cpp"
>
</File>
diff --git a/iniFile/iniFile.h b/iniFile/iniFile.h
index ebbcc5081..aef45c094 100644
--- a/iniFile/iniFile.h
+++ b/iniFile/iniFile.h
@@ -154,7 +154,12 @@ public:
return SetValueI( keyname, valuename, int(value), create);
}
bool SetValueF( const std::string & keyname, const std::string & valuename, const double value, const bool create = true);
+
+ // tolua_end
+
bool SetValueV( const std::string & keyname, const std::string & valuename, char *format, ...);
+
+ // tolua_begin
// Deletes specified value.
// Returns true if value existed and deleted, false otherwise.
diff --git a/source/AllToLua.pkg b/source/AllToLua.pkg
index 7041211b5..cd22aba0a 100644
--- a/source/AllToLua.pkg
+++ b/source/AllToLua.pkg
@@ -63,3 +63,11 @@ $cfile "LuaWindow.h"
+
+// Need to declare this class so that the usertype is properly registered in Bindings.cpp -
+// it seems impossible to register a usertype in ManualBindings.cpp
+class cLineBlockTracer;
+
+
+
+
diff --git a/source/Bindings.cpp b/source/Bindings.cpp
index df45cb1b3..fd953e29d 100644
--- a/source/Bindings.cpp
+++ b/source/Bindings.cpp
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 08/02/13 08:41:18.
+** Generated automatically by tolua++-1.0.92 on 08/07/13 12:06:03.
*/
#ifndef __cplusplus
@@ -202,8 +202,11 @@ static int tolua_collect_Vector3d (lua_State* tolua_S)
static void tolua_reg_types (lua_State* tolua_S)
{
tolua_usertype(tolua_S,"TakeDamageInfo");
- tolua_usertype(tolua_S,"cCraftingRecipe");
tolua_usertype(tolua_S,"cPlugin_NewLua");
+ tolua_usertype(tolua_S,"cCraftingGrid");
+ tolua_usertype(tolua_S,"cCraftingRecipe");
+ tolua_usertype(tolua_S,"cPlugin");
+ tolua_usertype(tolua_S,"cWindow");
tolua_usertype(tolua_S,"cStringMap");
tolua_usertype(tolua_S,"cItemGrid");
tolua_usertype(tolua_S,"cBlockArea");
@@ -211,42 +214,42 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cLuaWindow");
tolua_usertype(tolua_S,"cInventory");
tolua_usertype(tolua_S,"cRoot");
- tolua_usertype(tolua_S,"cWindow");
- tolua_usertype(tolua_S,"cCraftingGrid");
- tolua_usertype(tolua_S,"cTracer");
- tolua_usertype(tolua_S,"cPickup");
- tolua_usertype(tolua_S,"cItems");
+ tolua_usertype(tolua_S,"cCuboid");
+ tolua_usertype(tolua_S,"std::vector<cIniFile::key>");
tolua_usertype(tolua_S,"cGroup");
+ tolua_usertype(tolua_S,"cPickup");
+ tolua_usertype(tolua_S,"std::vector<std::string>");
+ tolua_usertype(tolua_S,"cTracer");
tolua_usertype(tolua_S,"cClientHandle");
tolua_usertype(tolua_S,"cChunkDesc");
tolua_usertype(tolua_S,"cFurnaceRecipe");
- tolua_usertype(tolua_S,"cCuboid");
- tolua_usertype(tolua_S,"cChatColor");
tolua_usertype(tolua_S,"Vector3i");
- tolua_usertype(tolua_S,"cEntity");
+ tolua_usertype(tolua_S,"cChatColor");
+ tolua_usertype(tolua_S,"cWorld");
+ tolua_usertype(tolua_S,"Lua__cPickup");
tolua_usertype(tolua_S,"Lua__cWebPlugin");
- tolua_usertype(tolua_S,"cPlugin");
tolua_usertype(tolua_S,"cCraftingRecipes");
+ tolua_usertype(tolua_S,"cEntity");
tolua_usertype(tolua_S,"cItem");
tolua_usertype(tolua_S,"Vector3f");
- tolua_usertype(tolua_S,"Lua__cPickup");
+ tolua_usertype(tolua_S,"cWebPlugin");
tolua_usertype(tolua_S,"cDropSpenserEntity");
tolua_usertype(tolua_S,"Lua__cPlayer");
- tolua_usertype(tolua_S,"cWebPlugin");
+ tolua_usertype(tolua_S,"cWebAdmin");
tolua_usertype(tolua_S,"cChestEntity");
tolua_usertype(tolua_S,"cDispenserEntity");
- tolua_usertype(tolua_S,"cWebAdmin");
+ tolua_usertype(tolua_S,"sWebAdminPage");
tolua_usertype(tolua_S,"cBlockEntity");
tolua_usertype(tolua_S,"cCriticalSection");
tolua_usertype(tolua_S,"HTTPTemplateRequest");
- tolua_usertype(tolua_S,"sWebAdminPage");
tolua_usertype(tolua_S,"HTTPRequest");
tolua_usertype(tolua_S,"HTTPFormData");
tolua_usertype(tolua_S,"cFurnaceEntity");
- tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"cDropperEntity");
+ tolua_usertype(tolua_S,"cLineBlockTracer");
+ tolua_usertype(tolua_S,"cPluginManager");
tolua_usertype(tolua_S,"cIniFile");
- tolua_usertype(tolua_S,"cWorld");
+ tolua_usertype(tolua_S,"cBlockEntityWithItems");
tolua_usertype(tolua_S,"cListeners");
tolua_usertype(tolua_S,"cPawn");
tolua_usertype(tolua_S,"cPlayer");
@@ -254,7 +257,7 @@ static void tolua_reg_types (lua_State* tolua_S)
tolua_usertype(tolua_S,"cBlockEntityWindowOwner");
tolua_usertype(tolua_S,"cItemGrid::cListener");
tolua_usertype(tolua_S,"cServer");
- tolua_usertype(tolua_S,"cBlockEntityWithItems");
+ tolua_usertype(tolua_S,"cItems");
tolua_usertype(tolua_S,"Lua__cEntity");
tolua_usertype(tolua_S,"Vector3d");
}
@@ -267,16 +270,14 @@ static int tolua_AllToLua_cIniFile_new00(lua_State* tolua_S)
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"cIniFile",0,&tolua_err) ||
- !tolua_iscppstring(tolua_S,2,1,&tolua_err) ||
- !tolua_isnoobj(tolua_S,3,&tolua_err)
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
- const std::string iniPath = ((const std::string) tolua_tocppstring(tolua_S,2,""));
{
- cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)(iniPath));
+ cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)());
tolua_pushusertype(tolua_S,(void*)tolua_ret,"cIniFile");
}
}
@@ -297,16 +298,14 @@ static int tolua_AllToLua_cIniFile_new00_local(lua_State* tolua_S)
tolua_Error tolua_err;
if (
!tolua_isusertable(tolua_S,1,"cIniFile",0,&tolua_err) ||
- !tolua_iscppstring(tolua_S,2,1,&tolua_err) ||
- !tolua_isnoobj(tolua_S,3,&tolua_err)
+ !tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
- const std::string iniPath = ((const std::string) tolua_tocppstring(tolua_S,2,""));
{
- cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)(iniPath));
+ cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)());
tolua_pushusertype(tolua_S,(void*)tolua_ret,"cIniFile");
tolua_register_gc(tolua_S,lua_gettop(tolua_S));
}
@@ -320,6 +319,59 @@ static int tolua_AllToLua_cIniFile_new00_local(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
+/* method: new of class cIniFile */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_new01
+static int tolua_AllToLua_cIniFile_new01(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cIniFile",0,&tolua_err) ||
+ !tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const std::string a_Path = ((const std::string) tolua_tocppstring(tolua_S,2,0));
+ {
+ cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)(a_Path));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cIniFile");
+ tolua_pushcppstring(tolua_S,(const char*)a_Path);
+ }
+ }
+ return 2;
+tolua_lerror:
+ return tolua_AllToLua_cIniFile_new00(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
+/* method: new_local of class cIniFile */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_new01_local
+static int tolua_AllToLua_cIniFile_new01_local(lua_State* tolua_S)
+{
+ tolua_Error tolua_err;
+ if (
+ !tolua_isusertable(tolua_S,1,"cIniFile",0,&tolua_err) ||
+ !tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
+ )
+ goto tolua_lerror;
+ else
+ {
+ const std::string a_Path = ((const std::string) tolua_tocppstring(tolua_S,2,0));
+ {
+ cIniFile* tolua_ret = (cIniFile*) Mtolua_new((cIniFile)(a_Path));
+ tolua_pushusertype(tolua_S,(void*)tolua_ret,"cIniFile");
+ tolua_register_gc(tolua_S,lua_gettop(tolua_S));
+ tolua_pushcppstring(tolua_S,(const char*)a_Path);
+ }
+ }
+ return 2;
+tolua_lerror:
+ return tolua_AllToLua_cIniFile_new00_local(tolua_S);
+}
+#endif //#ifndef TOLUA_DISABLE
+
/* method: CaseSensitive of class cIniFile */
#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_CaseSensitive00
static int tolua_AllToLua_cIniFile_CaseSensitive00(lua_State* tolua_S)
@@ -433,7 +485,7 @@ static int tolua_AllToLua_cIniFile_Path01(lua_State* tolua_S)
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Path'", NULL);
#endif
{
- std::string tolua_ret = (std::string) self->Path();
+ const std::string tolua_ret = (const std::string) self->Path();
tolua_pushcppstring(tolua_S,(const char*)tolua_ret);
}
}
@@ -485,18 +537,20 @@ static int tolua_AllToLua_cIniFile_ReadFile00(lua_State* tolua_S)
tolua_Error tolua_err;
if (
!tolua_isusertype(tolua_S,1,"cIniFile",0,&tolua_err) ||
- !tolua_isnoobj(tolua_S,2,&tolua_err)
+ !tolua_isboolean(tolua_S,2,1,&tolua_err) ||
+ !tolua_isnoobj(tolua_S,3,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
+ bool a_AllowExampleRedirect = ((bool) tolua_toboolean(tolua_S,2,true));
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'ReadFile'", NULL);
#endif
{
- bool tolua_ret = (bool) self->ReadFile();
+ bool tolua_ret = (bool) self->ReadFile(a_AllowExampleRedirect);
tolua_pushboolean(tolua_S,(bool)tolua_ret);
}
}
@@ -516,14 +570,14 @@ static int tolua_AllToLua_cIniFile_WriteFile00(lua_State* tolua_S)
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
if (
- !tolua_isusertype(tolua_S,1,"cIniFile",0,&tolua_err) ||
+ !tolua_isusertype(tolua_S,1,"const cIniFile",0,&tolua_err) ||
!tolua_isnoobj(tolua_S,2,&tolua_err)
)
goto tolua_lerror;
else
#endif
{
- cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
+ const cIniFile* self = (const cIniFile*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'WriteFile'", NULL);
#endif
@@ -541,9 +595,9 @@ static int tolua_AllToLua_cIniFile_WriteFile00(lua_State* tolua_S)
}
#endif //#ifndef TOLUA_DISABLE
-/* method: Erase of class cIniFile */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_Erase00
-static int tolua_AllToLua_cIniFile_Erase00(lua_State* tolua_S)
+/* method: Clear of class cIniFile */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_Clear00
+static int tolua_AllToLua_cIniFile_Clear00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
@@ -557,24 +611,24 @@ static int tolua_AllToLua_cIniFile_Erase00(lua_State* tolua_S)
{
cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Erase'", NULL);
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Clear'", NULL);
#endif
{
- self->Erase();
+ self->Clear();
}
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'Erase'.",&tolua_err);
+ tolua_error(tolua_S,"#ferror in function 'Clear'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
-/* method: Clear of class cIniFile */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_Clear00
-static int tolua_AllToLua_cIniFile_Clear00(lua_State* tolua_S)
+/* method: Reset of class cIniFile */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_Reset00
+static int tolua_AllToLua_cIniFile_Reset00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
@@ -588,24 +642,24 @@ static int tolua_AllToLua_cIniFile_Clear00(lua_State* tolua_S)
{
cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Clear'", NULL);
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Reset'", NULL);
#endif
{
- self->Clear();
+ self->Reset();
}
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'Clear'.",&tolua_err);
+ tolua_error(tolua_S,"#ferror in function 'Reset'.",&tolua_err);
return 0;
#endif
}
#endif //#ifndef TOLUA_DISABLE
-/* method: Reset of class cIniFile */
-#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_Reset00
-static int tolua_AllToLua_cIniFile_Reset00(lua_State* tolua_S)
+/* method: Erase of class cIniFile */
+#ifndef TOLUA_DISABLE_tolua_AllToLua_cIniFile_Erase00
+static int tolua_AllToLua_cIniFile_Erase00(lua_State* tolua_S)
{
#ifndef TOLUA_RELEASE
tolua_Error tolua_err;
@@ -619,16 +673,16 @@ static int tolua_AllToLua_cIniFile_Reset00(lua_State* tolua_S)
{
cIniFile* self = (cIniFile*) tolua_tousertype(tolua_S,1,0);
#ifndef TOLUA_RELEASE
- if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Reset'", NULL);
+ if (!self) tolua_error(tolua_S,"invalid 'self' in function 'Erase'", NULL);
#endif
{
- self->Reset();
+ self->Erase();
}
}
return 0;
#ifndef TOLUA_RELEASE
tolua_lerror:
- tolua_error(tolua_S,"#ferror in function 'Reset'.",&tolua_err);
+ tolua_error(tolua_S,"#ferror in function 'Erase'.",&tolua_err);
return 0;
#endif
}
@@ -28476,6 +28530,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"new",tolua_AllToLua_cIniFile_new00);
tolua_function(tolua_S,"new_local",tolua_AllToLua_cIniFile_new00_local);
tolua_function(tolua_S,".call",tolua_AllToLua_cIniFile_new00_local);
+ tolua_function(tolua_S,"new",tolua_AllToLua_cIniFile_new01);
+ tolua_function(tolua_S,"new_local",tolua_AllToLua_cIniFile_new01_local);
+ tolua_function(tolua_S,".call",tolua_AllToLua_cIniFile_new01_local);
tolua_function(tolua_S,"CaseSensitive",tolua_AllToLua_cIniFile_CaseSensitive00);
tolua_function(tolua_S,"CaseInsensitive",tolua_AllToLua_cIniFile_CaseInsensitive00);
tolua_function(tolua_S,"Path",tolua_AllToLua_cIniFile_Path00);
@@ -28483,9 +28540,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"SetPath",tolua_AllToLua_cIniFile_SetPath00);
tolua_function(tolua_S,"ReadFile",tolua_AllToLua_cIniFile_ReadFile00);
tolua_function(tolua_S,"WriteFile",tolua_AllToLua_cIniFile_WriteFile00);
- tolua_function(tolua_S,"Erase",tolua_AllToLua_cIniFile_Erase00);
tolua_function(tolua_S,"Clear",tolua_AllToLua_cIniFile_Clear00);
tolua_function(tolua_S,"Reset",tolua_AllToLua_cIniFile_Reset00);
+ tolua_function(tolua_S,"Erase",tolua_AllToLua_cIniFile_Erase00);
tolua_function(tolua_S,"FindKey",tolua_AllToLua_cIniFile_FindKey00);
tolua_function(tolua_S,"FindValue",tolua_AllToLua_cIniFile_FindValue00);
tolua_function(tolua_S,"NumKeys",tolua_AllToLua_cIniFile_NumKeys00);
@@ -28699,6 +28756,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_constant(tolua_S,"E_BLOCK_QUARTZ_BLOCK",E_BLOCK_QUARTZ_BLOCK);
tolua_constant(tolua_S,"E_BLOCK_ACTIVATOR_RAIL",E_BLOCK_ACTIVATOR_RAIL);
tolua_constant(tolua_S,"E_BLOCK_DROPPER",E_BLOCK_DROPPER);
+ tolua_constant(tolua_S,"E_BLOCK_CARPET",E_BLOCK_CARPET);
tolua_constant(tolua_S,"E_BLOCK_NUMBER_OF_TYPES",E_BLOCK_NUMBER_OF_TYPES);
tolua_constant(tolua_S,"E_BLOCK_MAX_TYPE_ID",E_BLOCK_MAX_TYPE_ID);
tolua_constant(tolua_S,"E_ITEM_EMPTY",E_ITEM_EMPTY);
@@ -30283,6 +30341,9 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
tolua_function(tolua_S,"GetContents",tolua_AllToLua_cLuaWindow_GetContents00);
tolua_variable(tolua_S,"__cItemGrid__cListener__",tolua_get_cLuaWindow___cItemGrid__cListener__,NULL);
tolua_endmodule(tolua_S);
+ tolua_cclass(tolua_S,"cLineBlockTracer","cLineBlockTracer","",NULL);
+ tolua_beginmodule(tolua_S,"cLineBlockTracer");
+ tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
return 1;
}
diff --git a/source/Bindings.h b/source/Bindings.h
index 6dfe855d3..a5654c062 100644
--- a/source/Bindings.h
+++ b/source/Bindings.h
@@ -1,6 +1,6 @@
/*
** Lua binding: AllToLua
-** Generated automatically by tolua++-1.0.92 on 08/02/13 08:41:19.
+** Generated automatically by tolua++-1.0.92 on 08/07/13 12:06:04.
*/
/* Exported function */
diff --git a/source/BlockEntities/ChestEntity.cpp b/source/BlockEntities/ChestEntity.cpp
index 24d2aef11..d5cd076be 100644
--- a/source/BlockEntities/ChestEntity.cpp
+++ b/source/BlockEntities/ChestEntity.cpp
@@ -123,7 +123,7 @@ void cChestEntity::UsedBy(cPlayer * a_Player)
// We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first.
// The few false positives aren't much to worry about
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(m_PosX, m_PosY, m_PosZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
m_World->MarkChunkDirty(ChunkX, ChunkZ);
}
diff --git a/source/BlockEntities/HopperEntity.cpp b/source/BlockEntities/HopperEntity.cpp
index 23e4b8096..591db7b4d 100644
--- a/source/BlockEntities/HopperEntity.cpp
+++ b/source/BlockEntities/HopperEntity.cpp
@@ -125,7 +125,7 @@ void cHopperEntity::UsedBy(cPlayer * a_Player)
// We cannot properly detect contents change, but such a change doesn't happen without a player opening the chest first.
// The few false positives aren't much to worry about
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(m_PosX, m_PosY, m_PosZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(m_PosX, m_PosZ, ChunkX, ChunkZ);
m_World->MarkChunkDirty(ChunkX, ChunkZ);
}
diff --git a/source/BlockTracer.h b/source/BlockTracer.h
new file mode 100644
index 000000000..6d67f1052
--- /dev/null
+++ b/source/BlockTracer.h
@@ -0,0 +1,104 @@
+
+// BlockTracer.h
+
+// Declares the classes common for all blocktracers
+
+
+
+
+
+#pragma once
+
+
+
+
+
+// fwd: World.h
+class cWorld;
+
+
+
+
+
+class cBlockTracer abstract
+{
+public:
+ /** The callback class is used to notify the caller of individual events that are being traced.
+ */
+ class cCallbacks abstract
+ {
+ public:
+ /** Called on each block encountered along the path, including the first block (path start)
+ When this callback returns true, the tracing is aborted.
+ */
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
+
+ /** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded
+ When this callback returns true, the tracing is aborted.
+ */
+ virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) { return false; }
+
+ /** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
+ The coords specify the exact point at which the path exited the world.
+ If this callback returns true, the tracing is aborted.
+ Note that some paths can go out of the world and come back again (parabola),
+ in such a case this callback is followed by OnIntoWorld() and further OnNextBlock() calls
+ */
+ virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) { return false; }
+
+ /** Called when the path goes into the world, from either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
+ The coords specify the exact point at which the path entered the world.
+ If this callback returns true, the tracing is aborted.
+ Note that some paths can go out of the world and come back again (parabola),
+ in such a case this callback is followed by further OnNextBlock() calls
+ */
+ virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) { return false; }
+
+ /** Called when the path is sure not to hit any more blocks.
+ Note that for some shapes this might never happen (line with constant Y)
+ */
+ virtual void OnNoMoreHits(void) {}
+
+ /** Called when the block tracing walks into a chunk that is not allocated.
+ This usually means that the tracing is aborted.
+ */
+ virtual void OnNoChunk(void) {}
+ } ;
+
+
+ /// Creates the BlockTracer parent with the specified callbacks
+ cBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) :
+ m_World(&a_World),
+ m_Callbacks(&a_Callbacks)
+ {
+ }
+
+
+ /// Sets new world, returns the old one. Note that both need to be valid
+ cWorld & SetWorld(cWorld & a_World)
+ {
+ cWorld & Old = *m_World;
+ m_World = &a_World;
+ return Old;
+ }
+
+
+ /// Sets new callbacks, returns the old ones. Note that both need to be valid
+ cCallbacks & SetCallbacks(cCallbacks & a_NewCallbacks)
+ {
+ cCallbacks & Old = *m_Callbacks;
+ m_Callbacks = &a_NewCallbacks;
+ return Old;
+ }
+
+protected:
+ /// The world upon which to operate
+ cWorld * m_World;
+
+ /// The callback to use for reporting
+ cCallbacks * m_Callbacks;
+} ;
+
+
+
+
diff --git a/source/ChunkDef.h b/source/ChunkDef.h
index 7f9c0ca98..3e78b59b1 100644
--- a/source/ChunkDef.h
+++ b/source/ChunkDef.h
@@ -137,7 +137,7 @@ public:
/// Converts absolute block coords into relative (chunk + block) coords:
inline static void AbsoluteToRelative(/* in-out */ int & a_X, int & a_Y, int & a_Z, /* out */ int & a_ChunkX, int & a_ChunkZ )
{
- BlockToChunk(a_X, a_Y, a_Z, a_ChunkX, a_ChunkZ);
+ BlockToChunk(a_X, a_Z, a_ChunkX, a_ChunkZ);
a_X = a_X - a_ChunkX * Width;
a_Z = a_Z - a_ChunkZ * Width;
@@ -145,9 +145,8 @@ public:
/// Converts absolute block coords to chunk coords:
- inline static void BlockToChunk( int a_X, int a_Y, int a_Z, int & a_ChunkX, int & a_ChunkZ )
+ inline static void BlockToChunk(int a_X, int a_Z, int & a_ChunkX, int & a_ChunkZ)
{
- (void)a_Y;
a_ChunkX = a_X / Width;
if ((a_X < 0) && (a_X % Width != 0))
{
diff --git a/source/ChunkMap.cpp b/source/ChunkMap.cpp
index 0db4b898a..0d49ce9c4 100644
--- a/source/ChunkMap.cpp
+++ b/source/ChunkMap.cpp
@@ -345,7 +345,7 @@ void cChunkMap::BroadcastBlockAction(int a_BlockX, int a_BlockY, int a_BlockZ, c
x = a_BlockX;
y = a_BlockY;
z = a_BlockZ;
- cChunkDef::BlockToChunk(x, y, z, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(x, z, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if (Chunk == NULL)
{
@@ -364,7 +364,7 @@ void cChunkMap::BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_blockX, a_blockY, a_blockZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_blockX, a_blockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@@ -382,7 +382,7 @@ void cChunkMap::BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, c
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
@@ -592,7 +592,7 @@ void cChunkMap::BroadcastSoundEffect(const AString & a_SoundName, int a_SrcX, in
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcY / 8, a_SrcZ / 8, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcZ / 8, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@@ -611,7 +611,7 @@ void cChunkMap::BroadcastSoundParticleEffect(int a_EffectID, int a_SrcX, int a_S
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcY / 8, a_SrcZ / 8, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_SrcX / 8, a_SrcZ / 8, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@@ -645,7 +645,7 @@ void cChunkMap::BroadcastThunderbolt(int a_BlockX, int a_BlockY, int a_BlockZ, c
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@@ -664,7 +664,7 @@ void cChunkMap::BroadcastUseBed(const cEntity & a_Entity, int a_BlockX, int a_Bl
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if (Chunk == NULL)
{
@@ -682,7 +682,7 @@ void cChunkMap::SendBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, cClien
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
@@ -700,7 +700,7 @@ void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i
// a_Player rclked block entity at the coords specified, handle it
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
@@ -713,11 +713,26 @@ void cChunkMap::UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, i
+bool cChunkMap::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback)
+{
+ cCSLock Lock(m_CSLayers);
+ cChunkPtr Chunk = GetChunkNoLoad(a_ChunkX, ZERO_CHUNK_Y, a_ChunkZ);
+ if (Chunk == NULL)
+ {
+ return false;
+ }
+ return a_Callback.Item(Chunk);
+}
+
+
+
+
+
void cChunkMap::WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ)
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, 0, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
@@ -735,8 +750,8 @@ void cChunkMap::WakeUpSimulatorsInArea(int a_MinBlockX, int a_MaxBlockX, int a_M
{
cSimulatorManager * SimMgr = m_World->GetSimulatorManager();
int MinChunkX, MinChunkZ, MaxChunkX, MaxChunkZ;
- cChunkDef::BlockToChunk(a_MinBlockX, ZERO_CHUNK_Y, a_MinBlockZ, MinChunkX, MinChunkZ);
- cChunkDef::BlockToChunk(a_MaxBlockX, ZERO_CHUNK_Y, a_MaxBlockZ, MaxChunkX, MaxChunkZ);
+ cChunkDef::BlockToChunk(a_MinBlockX, a_MinBlockZ, MinChunkX, MinChunkZ);
+ cChunkDef::BlockToChunk(a_MaxBlockX, a_MaxBlockZ, MaxChunkX, MaxChunkZ);
for (int z = MinChunkZ; z <= MaxChunkZ; z++)
{
int MinZ = std::max(a_MinBlockZ, z * cChunkDef::Width);
@@ -1903,7 +1918,7 @@ bool cChunkMap::SetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, const ASt
{
cCSLock Lock(m_CSLayers);
int ChunkX, ChunkZ;
- cChunkDef::BlockToChunk(a_BlockX, a_BlockY, a_BlockZ, ChunkX, ChunkZ);
+ cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, ChunkX, ChunkZ);
cChunkPtr Chunk = GetChunkNoGen(ChunkX, ZERO_CHUNK_Y, ChunkZ);
if ((Chunk == NULL) || !Chunk->IsValid())
{
diff --git a/source/ChunkMap.h b/source/ChunkMap.h
index 899f290c5..183031808 100644
--- a/source/ChunkMap.h
+++ b/source/ChunkMap.h
@@ -35,6 +35,7 @@ typedef cItemCallback<cDispenserEntity> cDispenserCallback;
typedef cItemCallback<cDropperEntity> cDropperCallback;
typedef cItemCallback<cDropSpenserEntity> cDropSpenserCallback;
typedef cItemCallback<cFurnaceEntity> cFurnaceCallback;
+typedef cItemCallback<cChunk> cChunkCallback;
@@ -79,6 +80,9 @@ public:
/// a_Player rclked block entity at the coords specified, handle it
void UseBlockEntity(cPlayer * a_Player, int a_X, int a_Y, int a_Z);
+ /// Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback
+ bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback);
+
/// Wakes up simulators for the specified block
void WakeUpSimulators(int a_BlockX, int a_BlockY, int a_BlockZ);
diff --git a/source/Item.h b/source/Item.h
index fc54da51d..fee861050 100644
--- a/source/Item.h
+++ b/source/Item.h
@@ -55,7 +55,10 @@ public:
{
if (!IsValidItem(m_ItemType))
{
- LOGWARNING("%s: creating an invalid item type (%d), resetting to empty.", __FUNCTION__, a_ItemType);
+ if (m_ItemType != E_BLOCK_AIR)
+ {
+ LOGWARNING("%s: creating an invalid item type (%d), resetting to empty.", __FUNCTION__, a_ItemType);
+ }
Empty();
}
}
diff --git a/source/LineBlockTracer.cpp b/source/LineBlockTracer.cpp
new file mode 100644
index 000000000..03464314a
--- /dev/null
+++ b/source/LineBlockTracer.cpp
@@ -0,0 +1,261 @@
+
+// LineBlockTracer.cpp
+
+// Implements the cLineBlockTracer class representing a cBlockTracer that traces along a straight line between two points
+
+#include "Globals.h"
+#include "LineBlockTracer.h"
+#include "Vector3d.h"
+#include "World.h"
+#include "Chunk.h"
+
+
+
+
+
+
+cLineBlockTracer::cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks) :
+ super(a_World, a_Callbacks)
+{
+}
+
+
+
+
+
+bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks & a_Callbacks, const Vector3d & a_Start, const Vector3d & a_End)
+{
+ cLineBlockTracer Tracer(a_World, a_Callbacks);
+ return Tracer.Trace(a_Start.x, a_Start.y, a_Start.z, a_End.x, a_End.y, a_End.z);
+}
+
+
+
+
+
+bool cLineBlockTracer::Trace(cWorld & a_World, cBlockTracer::cCallbacks &a_Callbacks, double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ)
+{
+ cLineBlockTracer Tracer(a_World, a_Callbacks);
+ return Tracer.Trace(a_StartX, a_StartY, a_StartZ, a_EndX, a_EndY, a_EndZ);
+}
+
+
+
+
+
+bool cLineBlockTracer::Trace(double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ)
+{
+ // Initialize the member veriables:
+ m_StartX = a_StartX;
+ m_StartY = a_StartY;
+ m_StartZ = a_StartZ;
+ m_EndX = a_EndX;
+ m_EndY = a_EndY;
+ m_EndZ = a_EndZ;
+ m_DirX = (m_StartX < m_EndX) ? 1 : -1;
+ m_DirY = (m_StartY < m_EndY) ? 1 : -1;
+ m_DirZ = (m_StartZ < m_EndZ) ? 1 : -1;
+
+ // Check the start coords, adjust into the world:
+ if (m_StartY < 0)
+ {
+ if (m_EndY < 0)
+ {
+ // Nothing to trace
+ m_Callbacks->OnNoMoreHits();
+ return true;
+ }
+ FixStartBelowWorld();
+ m_Callbacks->OnIntoWorld(m_StartX, m_StartY, m_StartZ);
+ }
+ else if (m_StartY >= cChunkDef::Height)
+ {
+ if (m_EndY >= cChunkDef::Height)
+ {
+ m_Callbacks->OnNoMoreHits();
+ return true;
+ }
+ FixStartAboveWorld();
+ m_Callbacks->OnIntoWorld(m_StartX, m_StartY, m_StartZ);
+ }
+
+ m_CurrentX = (int)floor(m_StartX);
+ m_CurrentY = (int)floor(m_StartY);
+ m_CurrentZ = (int)floor(m_StartZ);
+
+ m_DiffX = m_EndX - m_StartX;
+ m_DiffY = m_EndY - m_StartY;
+ m_DiffZ = m_EndZ - m_StartZ;
+
+ // The actual trace is handled with ChunkMapCS locked by calling our Item() for the specified chunk
+ int BlockX = (int)floor(m_StartX);
+ int BlockZ = (int)floor(m_StartZ);
+ int ChunkX, ChunkZ;
+ cChunkDef::BlockToChunk(BlockX, BlockZ, ChunkX, ChunkZ);
+ return m_World->DoWithChunk(ChunkX, ChunkZ, *this);
+}
+
+
+
+
+
+void cLineBlockTracer::FixStartAboveWorld(void)
+{
+ // We must set the start Y to less than cChunkDef::Height so that it is considered inside the world later on
+ // Therefore we use an EPS-offset from the height, as small as reasonably possible.
+ const double Height = (double)cChunkDef::Height - 0.00001;
+ CalcXZIntersection(Height, m_StartX, m_StartZ);
+ m_StartY = Height;
+}
+
+
+
+
+
+void cLineBlockTracer::FixStartBelowWorld(void)
+{
+ CalcXZIntersection(0, m_StartX, m_StartZ);
+ m_StartY = 0;
+}
+
+
+
+
+
+void cLineBlockTracer::CalcXZIntersection(double a_Y, double & a_IntersectX, double & a_IntersectZ)
+{
+ double Ratio = (m_StartY - a_Y) / (m_StartY - m_EndY);
+ a_IntersectX = m_StartX + (m_EndX - m_StartX) * Ratio;
+ a_IntersectZ = m_StartZ + (m_EndZ - m_StartZ) * Ratio;
+}
+
+
+
+
+
+bool cLineBlockTracer::MoveToNextBlock(void)
+{
+ // Find out which of the current block's walls gets hit by the path:
+ static const double EPS = 0.00001;
+ double Coeff = 1;
+ enum eDirection
+ {
+ dirNONE,
+ dirX,
+ dirY,
+ dirZ,
+ } Direction = dirNONE;
+ if (abs(m_DiffX) > EPS)
+ {
+ double DestX = (m_DirX > 0) ? (m_CurrentX + 1) : m_CurrentX;
+ Coeff = (DestX - m_StartX) / m_DiffX;
+ if (Coeff <= 1)
+ {
+ Direction = dirX;
+ }
+ }
+ if (abs(m_DiffY) > EPS)
+ {
+ double DestY = (m_DirY > 0) ? (m_CurrentY + 1) : m_CurrentY;
+ double CoeffY = (DestY - m_StartY) / m_DiffY;
+ if (CoeffY < Coeff)
+ {
+ Coeff = CoeffY;
+ Direction = dirY;
+ }
+ }
+ if (abs(m_DiffZ) > EPS)
+ {
+ double DestZ = (m_DirZ > 0) ? (m_CurrentZ + 1) : m_CurrentZ;
+ double CoeffZ = (DestZ - m_StartZ) / m_DiffZ;
+ if (CoeffZ < Coeff)
+ {
+ Coeff = CoeffZ;
+ Direction = dirZ;
+ }
+ }
+
+ // Based on the wall hit, adjust the current coords
+ switch (Direction)
+ {
+ case dirX: m_CurrentX += m_DirX; break;
+ case dirY: m_CurrentY += m_DirY; break;
+ case dirZ: m_CurrentZ += m_DirZ; break;
+ case dirNONE: return false;
+ }
+ return true;
+}
+
+
+
+
+
+bool cLineBlockTracer::Item(cChunk * a_Chunk)
+{
+ ASSERT((m_CurrentY >= 0) && (m_CurrentY < cChunkDef::Height)); // This should be provided by FixStartAboveWorld() / FixStartBelowWorld()
+
+ // This is the actual line tracing loop.
+ bool Finished = false;
+ while (true)
+ {
+ // Report the current block through the callbacks:
+ if (a_Chunk == NULL)
+ {
+ m_Callbacks->OnNoChunk();
+ return false;
+ }
+ if (a_Chunk->IsValid())
+ {
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width;
+ int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width;
+ a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta);
+ if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta))
+ {
+ // The callback terminated the trace
+ return false;
+ }
+ }
+ else
+ {
+ if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ))
+ {
+ // The callback terminated the trace
+ return false;
+ }
+ }
+
+ // Move to next block
+ if (!MoveToNextBlock())
+ {
+ // We've reached the end
+ m_Callbacks->OnNoMoreHits();
+ return true;
+ }
+
+ // Update the current chunk
+ if (a_Chunk != NULL)
+ {
+ a_Chunk = a_Chunk->GetNeighborChunk(m_CurrentX, m_CurrentZ);
+ }
+
+ if ((m_CurrentY < 0) || (m_CurrentY >= cChunkDef::Height))
+ {
+ // We've gone out of the world, that's the end of this trace
+ double IntersectX, IntersectZ;
+ CalcXZIntersection(m_CurrentY, IntersectX, IntersectZ);
+ if (m_Callbacks->OnOutOfWorld(IntersectX, m_CurrentY, IntersectZ))
+ {
+ // The callback terminated the trace
+ return false;
+ }
+ m_Callbacks->OnNoMoreHits();
+ return true;
+ }
+ }
+}
+
+
+
+
diff --git a/source/LineBlockTracer.h b/source/LineBlockTracer.h
new file mode 100644
index 000000000..4616cb191
--- /dev/null
+++ b/source/LineBlockTracer.h
@@ -0,0 +1,84 @@
+
+// LineBlockTracer.h
+
+// Declares the cLineBlockTracer class representing a cBlockTracer that traces along a straight line between two points
+
+
+
+
+
+#pragma once
+
+#include "BlockTracer.h"
+
+
+
+
+
+// fwd: Chunk.h
+class cChunk;
+
+// fwd: cChunkMap.h
+typedef cItemCallback<cChunk> cChunkCallback;
+
+
+
+
+
+
+class cLineBlockTracer :
+ public cBlockTracer,
+ public cChunkCallback
+{
+ typedef cBlockTracer super;
+
+public:
+ cLineBlockTracer(cWorld & a_World, cCallbacks & a_Callbacks);
+
+ /// Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits())
+ bool Trace(double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ);
+
+ // Utility functions for simple one-line usage:
+ /// Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits())
+ static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, double a_StartX, double a_StartY, double a_StartZ, double a_EndX, double a_EndY, double a_EndZ);
+
+ /// Traces one line between Start and End; returns true if the entire line was traced (until OnNoMoreHits())
+ static bool Trace(cWorld & a_World, cCallbacks & a_Callbacks, const Vector3d & a_Start, const Vector3d & a_End);
+
+protected:
+ // The start point of the trace
+ double m_StartX, m_StartY, m_StartZ;
+
+ // The end point of the trace
+ double m_EndX, m_EndY, m_EndZ;
+
+ // The difference in coords, End - Start
+ double m_DiffX, m_DiffY, m_DiffZ;
+
+ // The increment at which the block coords are going from Start to End; either +1 or -1
+ int m_DirX, m_DirY, m_DirZ;
+
+ // The current block
+ int m_CurrentX, m_CurrentY, m_CurrentZ;
+
+
+ /// Adjusts the start point above the world to just at the world's top
+ void FixStartAboveWorld(void);
+
+ /// Adjusts the start point below the world to just at the world's bottom
+ void FixStartBelowWorld(void);
+
+ /// Calculates the XZ coords of an intersection with the specified Yconst plane; assumes that such an intersection exists
+ void CalcXZIntersection(double a_Y, double & a_IntersectX, double & a_IntersectZ);
+
+ /// Moves m_Current to the next block on the line; returns false if no move is possible (reached the end)
+ bool MoveToNextBlock(void);
+
+ // cChunkCallback overrides:
+ virtual bool Item(cChunk * a_Chunk) override;
+} ;
+
+
+
+
+
diff --git a/source/LuaScript.cpp b/source/LuaScript.cpp
index 8d92c238f..d406c2c02 100644
--- a/source/LuaScript.cpp
+++ b/source/LuaScript.cpp
@@ -6,34 +6,14 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "LuaScript.h"
-
-extern "C"
-{
-#include "lualib.h"
-}
-
#include "tolua++.h"
-#include "Bindings.h"
-#include "ManualBindings.h"
-
-// fwd: SQLite/lsqlite3.c
-extern "C"
-{
- LUALIB_API int luaopen_lsqlite3(lua_State * L);
-}
-
-// fwd: LuaExpat/lxplib.c:
-extern "C"
-{
- int luaopen_lxp(lua_State * L);
-}
cLuaScript::cLuaScript()
- : m_LuaState(NULL)
+ : m_LuaState("cLuaScript")
{
}
@@ -42,197 +22,45 @@ cLuaScript::cLuaScript()
-cLuaScript::~cLuaScript()
-{
- if( m_LuaState )
- {
- lua_close( m_LuaState );
- m_LuaState = 0;
- }
-}
-
-
-
-
-
void cLuaScript::Initialize()
{
// Check to see if this script has not been initialized before
- ASSERT(!m_LuaState);
+ ASSERT(!m_LuaState.IsValid());
// Create a Lua state and bind all libraries to it
- m_LuaState = lua_open();
- luaL_openlibs(m_LuaState);
- tolua_AllToLua_open(m_LuaState);
- ManualBindings::Bind(m_LuaState);
- luaopen_lsqlite3(m_LuaState);
- luaopen_lxp(m_LuaState);
+ m_LuaState.Create();
}
-bool cLuaScript::LoadFile( const char* a_FilePath )
+bool cLuaScript::LoadFile(const char * a_FilePath)
{
// Make sure the plugin is initialized
- ASSERT(m_LuaState);
-
- // Load the file into the Lua state
- int s = luaL_loadfile(m_LuaState, a_FilePath );
- if (ReportErrors(s))
- {
- return false;
- }
- return true;
-}
-
-
-
-
-
-bool cLuaScript::Execute()
-{
- // Make sure we got a Lua state
- ASSERT(m_LuaState);
-
- // Execute the script as it is right now
- int s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0);
- if( ReportErrors( s ) )
- {
- return false;
- }
- return true;
-}
-
-
-
-
-
-bool cLuaScript::ReportErrors( int a_Status )
-{
- if (a_Status == 0)
- {
- // No error to report
- return false;
- }
-
- // Status was set to error so get the error from the Lua state and log it
- LOGERROR("LUA: %s", lua_tostring(m_LuaState, -1));
- lua_pop(m_LuaState, 1);
-
- // Return true to indicate that an error was returned
- return true;
-}
-
-
-
-
-
-bool cLuaScript::LuaPushFunction( const char * a_FunctionName, bool a_bLogError /*= true*/ )
-{
- ASSERT(m_LuaState);
-
- // Find and push the function on the Lua stack
- lua_getglobal(m_LuaState, a_FunctionName);
-
- // Make sure we found a function
- if (!lua_isfunction(m_LuaState, -1))
- {
- if (a_bLogError)
- {
- LOGWARN("LUA: Could not find function %s()", a_FunctionName);
- }
-
- // Pop the pushed 'object' back
- lua_pop(m_LuaState, 1);
- return false;
- }
-
- // Successfully pushed a function to the Lua stack
- return true;
-}
+ ASSERT(m_LuaState.IsValid());
-
-
-
-
-bool cLuaScript::LuaCallFunction( int a_NumArgs, int a_NumResults, const char * a_FunctionName )
-{
- ASSERT(m_LuaState);
-
- // Make sure there's a lua function on the stack
- ASSERT(lua_isfunction(m_LuaState, -a_NumArgs - 1));
-
- // Call the desired function
- int s = lua_pcall(m_LuaState, a_NumArgs, a_NumResults, 0);
-
- // Check for errors
- if (ReportErrors(s))
- {
- LOGWARN("LUA: Error calling function %s()", a_FunctionName);
- return false;
- }
-
- // Successfully executed function
- return true;
-}
-
-
-
-
-
-bool cLuaScript::CallFunction( const char* a_Function, AString& ReturnedString )
-{
- // Make sure we have the required things to call a function
- ASSERT(m_LuaState);
- ASSERT(a_Function);
-
- // Push the desired function on the stack
- if (!LuaPushFunction(a_Function))
- {
- return false;
- }
-
- if (!LuaCallFunction(0, 1, a_Function))
- {
- return false;
- }
-
- if (lua_isstring(m_LuaState, -1))
- {
- ReturnedString = tolua_tostring(m_LuaState, -1, "");
- }
- lua_pop(m_LuaState, 1);
- return true;
+ return m_LuaState.LoadFile(a_FilePath);
}
-bool cLuaScript::CallFunction( const char* a_Function, const sLuaUsertype& a_UserType, AString& ReturnedString )
+bool cLuaScript::CallShowPage(cWebAdmin & a_WebAdmin, HTTPTemplateRequest & a_Request, AString & a_ReturnedString)
{
- // Make sure we have the required things to call a function
- ASSERT(m_LuaState);
- ASSERT(a_Function);
-
- // Push the desired function on the stack
- if (!LuaPushFunction(a_Function))
+ ASSERT(m_LuaState.IsValid());
+
+ m_LuaState.PushFunction("ShowPage");
+ m_LuaState.PushUserType(&a_WebAdmin, "cWebAdmin");
+ m_LuaState.PushUserType(&a_Request, "HTTPTemplateRequest");
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
-
- tolua_pushusertype(m_LuaState, a_UserType.Object, a_UserType.ClassName);
-
- if (!LuaCallFunction(1, 1, a_Function))
- {
- return false;
- }
-
if (lua_isstring(m_LuaState, -1))
{
- ReturnedString = tolua_tostring(m_LuaState, -1, "");
+ a_ReturnedString.assign(tolua_tostring(m_LuaState, -1, ""));
}
lua_pop(m_LuaState, 1);
return true;
@@ -241,38 +69,3 @@ bool cLuaScript::CallFunction( const char* a_Function, const sLuaUsertype& a_Use
-
-bool cLuaScript::CallFunction( const char* a_Function, const sLuaUsertype& a_UserType1, const sLuaUsertype& a_UserType2, AString& ReturnedString )
-{
- // Make sure we have the required things to call a function
- ASSERT(m_LuaState);
- ASSERT(a_Function);
-
- // Push the desired function on the stack
- if (!LuaPushFunction(a_Function))
- {
- return false;
- }
-
- tolua_pushusertype(m_LuaState, a_UserType1.Object, a_UserType1.ClassName);
- tolua_pushusertype(m_LuaState, a_UserType2.Object, a_UserType2.ClassName);
-
- if (!LuaCallFunction(2, 1, a_Function))
- {
- return false;
- }
-
- if (lua_isstring(m_LuaState, -1))
- {
- ReturnedString = tolua_tostring(m_LuaState, -1, "");
- }
- lua_pop(m_LuaState, 1);
- return true;
-}
-
-
-
-
-
-
-
diff --git a/source/LuaScript.h b/source/LuaScript.h
index f98b2e65b..99ccb3d49 100644
--- a/source/LuaScript.h
+++ b/source/LuaScript.h
@@ -9,19 +9,15 @@
#pragma once
-struct lua_State;
+#include "LuaState.h"
-struct sLuaUsertype
-{
- sLuaUsertype(void* a_pObject, const char* a_pClassName) : Object(a_pObject), ClassName(a_pClassName) {}
- //
- void* Object;
- const char* ClassName;
-} ;
+// fwd:
+class cWebAdmin;
+struct HTTPTemplateRequest;
@@ -30,32 +26,18 @@ struct sLuaUsertype
class cLuaScript
{
public:
- cLuaScript();
- ~cLuaScript();
+ cLuaScript(void);
/// Prepares a Lua state
- void Initialize();
+ void Initialize();
/// Load a Lua script on the given path
- bool LoadFile(const char* a_FilePath);
-
- /// Execute the loaded Lua script
- bool Execute();
+ bool LoadFile(const char * a_FilePath);
- /// Call a function on the Lua script. Put all overloads here
- bool CallFunction(const char* a_Function, AString& ReturnedString);
- bool CallFunction(const char* a_Function, const sLuaUsertype& a_UserType, AString& ReturnedString);
- bool CallFunction(const char* a_Function, const sLuaUsertype& a_UserType1, const sLuaUsertype& a_UserType2, AString& ReturnedString);
+ bool CallShowPage(cWebAdmin & a_WebAdmin, HTTPTemplateRequest & a_Request, AString & a_ReturnedString);
protected:
- /// Reports an error in the log if a_Status is flagged as an error. Returns true when a_Status is flagged as error, returns false when no error occured.
- bool ReportErrors(int a_Status);
-
- /// Helper functions for calling functions in Lua
- bool LuaPushFunction(const char * a_FunctionName, bool a_bLogError = true);
- bool LuaCallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName ); // a_FunctionName is only used for error messages, nothing else
-private:
- lua_State* m_LuaState;
+ cLuaState m_LuaState;
} ;
diff --git a/source/LuaState.cpp b/source/LuaState.cpp
new file mode 100644
index 000000000..664ba8147
--- /dev/null
+++ b/source/LuaState.cpp
@@ -0,0 +1,646 @@
+
+// LuaState.cpp
+
+// Implements the cLuaState class representing the wrapper over lua_State *, provides associated helper functions
+
+#include "Globals.h"
+#include "LuaState.h"
+
+extern "C"
+{
+ #include "lualib.h"
+}
+
+#include "tolua++.h"
+#include "Bindings.h"
+#include "ManualBindings.h"
+
+// fwd: SQLite/lsqlite3.c
+extern "C"
+{
+ LUALIB_API int luaopen_lsqlite3(lua_State * L);
+}
+
+// fwd: LuaExpat/lxplib.c:
+extern "C"
+{
+ int luaopen_lxp(lua_State * L);
+}
+
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cLuaState:
+
+cLuaState::cLuaState(const AString & a_SubsystemName) :
+ m_LuaState(NULL),
+ m_IsOwned(false),
+ m_SubsystemName(a_SubsystemName),
+ m_NumCurrentFunctionArgs(-1)
+{
+}
+
+
+
+
+
+cLuaState::cLuaState(lua_State * a_AttachState) :
+ m_LuaState(a_AttachState),
+ m_IsOwned(false),
+ m_SubsystemName("<attached>"),
+ m_NumCurrentFunctionArgs(-1)
+{
+}
+
+
+
+
+
+cLuaState::~cLuaState()
+{
+ if (IsValid())
+ {
+ if (m_IsOwned)
+ {
+ Close();
+ }
+ else
+ {
+ Detach();
+ }
+ }
+}
+
+
+
+
+
+void cLuaState::Create(void)
+{
+ if (m_LuaState != NULL)
+ {
+ LOGWARNING("%s: Trying to create an already-existing LuaState, ignoring.", __FUNCTION__);
+ return;
+ }
+ m_LuaState = lua_open();
+ luaL_openlibs(m_LuaState);
+ tolua_AllToLua_open(m_LuaState);
+ ManualBindings::Bind(m_LuaState);
+ luaopen_lsqlite3(m_LuaState);
+ luaopen_lxp(m_LuaState);
+ m_IsOwned = true;
+}
+
+
+
+
+
+void cLuaState::Close(void)
+{
+ if (m_LuaState == NULL)
+ {
+ LOGWARNING("%s: Trying to close an invalid LuaState, ignoring.", __FUNCTION__);
+ return;
+ }
+ if (!m_IsOwned)
+ {
+ LOGWARNING(
+ "%s: Detected mis-use, calling Close() on an attached state (0x%p). Detaching instead.",
+ __FUNCTION__, m_LuaState
+ );
+ Detach();
+ return;
+ }
+ lua_close(m_LuaState);
+ m_LuaState = NULL;
+ m_IsOwned = false;
+}
+
+
+
+
+
+void cLuaState::Attach(lua_State * a_State)
+{
+ if (m_LuaState != NULL)
+ {
+ LOGINFO("%s: Already contains a LuaState (0x%p), will be closed / detached.", __FUNCTION__, m_LuaState);
+ if (m_IsOwned)
+ {
+ Close();
+ }
+ else
+ {
+ Detach();
+ }
+ }
+ m_LuaState = a_State;
+ m_IsOwned = false;
+}
+
+
+
+
+
+void cLuaState::Detach(void)
+{
+ if (m_LuaState == NULL)
+ {
+ return;
+ }
+ if (m_IsOwned)
+ {
+ LOGWARNING(
+ "%s: Detected a mis-use, calling Detach() when the state is owned. Closing the owned state (0x%p).",
+ __FUNCTION__, m_LuaState
+ );
+ Close();
+ return;
+ }
+ m_LuaState = NULL;
+}
+
+
+
+
+
+bool cLuaState::LoadFile(const AString & a_FileName)
+{
+ ASSERT(IsValid());
+
+ // Load the file:
+ int s = luaL_loadfile(m_LuaState, a_FileName.c_str());
+ if (ReportErrors(s))
+ {
+ LOGWARNING("Can't load %s because of an error in file %s", m_SubsystemName.c_str(), a_FileName.c_str());
+ return false;
+ }
+
+ // Execute the globals:
+ s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0);
+ if (ReportErrors(s))
+ {
+ LOGWARNING("Error in %s in file %s", m_SubsystemName.c_str(), a_FileName.c_str());
+ return false;
+ }
+
+ return true;
+}
+
+
+
+
+
+bool cLuaState::PushFunction(const char * a_FunctionName, bool a_ShouldLogFailure /* = true */)
+{
+ ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack
+
+ if (!IsValid())
+ {
+ // This happens if cPlugin::Initialize() fails with an error
+ return false;
+ }
+
+ lua_getglobal(m_LuaState, a_FunctionName);
+ if (!lua_isfunction(m_LuaState, -1))
+ {
+ if (a_ShouldLogFailure)
+ {
+ LOGWARNING("Error in %s: Could not find function %s()", m_SubsystemName.c_str(), a_FunctionName);
+ }
+ lua_pop(m_LuaState, 1);
+ return false;
+ }
+ m_CurrentFunctionName.assign(a_FunctionName);
+ m_NumCurrentFunctionArgs = 0;
+ return true;
+}
+
+
+
+
+
+bool cLuaState::PushFunctionFromRegistry(int a_FnRef)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack
+
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // same as lua_getref()
+ if (!lua_isfunction(m_LuaState, -1))
+ {
+ lua_pop(m_LuaState, 1);
+ return false;
+ }
+ m_CurrentFunctionName = "<callback>";
+ m_NumCurrentFunctionArgs = 0;
+ return true;
+}
+
+
+
+
+
+bool cLuaState::PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs == -1); // If not, there's already something pushed onto the stack
+
+ lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_TableRef); // Get the table ref
+ if (!lua_istable(m_LuaState, -1))
+ {
+ // Not a table, bail out
+ lua_pop(m_LuaState, 1);
+ return false;
+ }
+ lua_getfield(m_LuaState, -1, a_FnName);
+ if (lua_isnil(m_LuaState, -1) || !lua_isfunction(m_LuaState, -1))
+ {
+ // Not a valid function, bail out
+ lua_pop(m_LuaState, 2);
+ return false;
+ }
+ lua_remove(m_LuaState, -2); // Remove the table ref from the stack
+ m_CurrentFunctionName = "<table_callback>";
+ m_NumCurrentFunctionArgs = 0;
+ return true;
+}
+
+
+
+
+
+void cLuaState::PushStringVector(const AStringVector & a_Vector)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ lua_createtable(m_LuaState, a_Vector.size(), 0);
+ int newTable = lua_gettop(m_LuaState);
+ int index = 1;
+ for (AStringVector::const_iterator itr = a_Vector.begin(), end = a_Vector.end(); itr != end; ++itr, ++index)
+ {
+ tolua_pushstring(m_LuaState, itr->c_str());
+ lua_rawseti(m_LuaState, newTable, index);
+ }
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushUserType(void * a_Object, const char * a_Type)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushusertype(m_LuaState, a_Object, a_Type);
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushNumber(int a_Value)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushnumber(m_LuaState, a_Value);
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushNumber(double a_Value)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushnumber(m_LuaState, a_Value);
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushString(const char * a_Value)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushstring(m_LuaState, a_Value);
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushBool(bool a_Value)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushboolean(m_LuaState, a_Value ? 1 : 0);
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushObject(cWorld * a_World)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushusertype(m_LuaState, a_World, "cWorld");
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushObject(cPlayer * a_Player)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushObject(cEntity * a_Entity)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushusertype(m_LuaState, a_Entity, "cEntity");
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushObject(cItem * a_Item)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushusertype(m_LuaState, a_Item, "cItem");
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushObject(cItems * a_Items)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushusertype(m_LuaState, a_Items, "cItems");
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushObject(cClientHandle * a_Client)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushusertype(m_LuaState, a_Client, "cClientHandle");
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+void cLuaState::PushObject(cPickup * a_Pickup)
+{
+ ASSERT(IsValid());
+ ASSERT(m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+
+ tolua_pushusertype(m_LuaState, a_Pickup, "cPickup");
+ m_NumCurrentFunctionArgs += 1;
+}
+
+
+
+
+
+bool cLuaState::CallFunction(int a_NumResults)
+{
+ ASSERT (m_NumCurrentFunctionArgs >= 0); // A function must be pushed to stack first
+ ASSERT(lua_isfunction(m_LuaState, -m_NumCurrentFunctionArgs - 1));
+
+ int s = lua_pcall(m_LuaState, m_NumCurrentFunctionArgs, a_NumResults, 0);
+ if (ReportErrors(s))
+ {
+ LOGWARNING("Error in %s calling function %s()", m_SubsystemName.c_str(), m_CurrentFunctionName.c_str());
+ m_NumCurrentFunctionArgs = -1;
+ m_CurrentFunctionName.clear();
+ return false;
+ }
+ m_NumCurrentFunctionArgs = -1;
+ m_CurrentFunctionName.clear();
+ return true;
+}
+
+
+
+
+
+bool cLuaState::CheckParamUserType(int a_StartParam, const char * a_UserType, int a_EndParam)
+{
+ ASSERT(IsValid());
+
+ if (a_EndParam < 0)
+ {
+ a_EndParam = a_StartParam;
+ }
+
+ tolua_Error tolua_err;
+ for (int i = a_StartParam; i <= a_EndParam; i++)
+ {
+ if (tolua_isusertype(m_LuaState, i, a_UserType, 0, &tolua_err))
+ {
+ continue;
+ }
+ // Not the correct parameter
+ lua_Debug entry;
+ VERIFY(lua_getstack(m_LuaState, 0, &entry));
+ VERIFY(lua_getinfo (m_LuaState, "n", &entry));
+ AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != NULL) ? entry.name : "?");
+ tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
+ return false;
+ } // for i - Param
+
+ // All params checked ok
+ return true;
+}
+
+
+
+
+
+bool cLuaState::CheckParamTable(int a_StartParam, int a_EndParam)
+{
+ ASSERT(IsValid());
+
+ if (a_EndParam < 0)
+ {
+ a_EndParam = a_StartParam;
+ }
+
+ tolua_Error tolua_err;
+ for (int i = a_StartParam; i <= a_EndParam; i++)
+ {
+ if (tolua_istable(m_LuaState, i, 0, &tolua_err))
+ {
+ continue;
+ }
+ // Not the correct parameter
+ lua_Debug entry;
+ VERIFY(lua_getstack(m_LuaState, 0, &entry));
+ VERIFY(lua_getinfo (m_LuaState, "n", &entry));
+ AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != NULL) ? entry.name : "?");
+ tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
+ return false;
+ } // for i - Param
+
+ // All params checked ok
+ return true;
+}
+
+
+
+
+
+bool cLuaState::CheckParamNumber(int a_StartParam, int a_EndParam)
+{
+ ASSERT(IsValid());
+
+ if (a_EndParam < 0)
+ {
+ a_EndParam = a_StartParam;
+ }
+
+ tolua_Error tolua_err;
+ for (int i = a_StartParam; i <= a_EndParam; i++)
+ {
+ if (tolua_isnumber(m_LuaState, i, 0, &tolua_err))
+ {
+ continue;
+ }
+ // Not the correct parameter
+ lua_Debug entry;
+ VERIFY(lua_getstack(m_LuaState, 0, &entry));
+ VERIFY(lua_getinfo (m_LuaState, "n", &entry));
+ AString ErrMsg = Printf("#ferror in function '%s'.", (entry.name != NULL) ? entry.name : "?");
+ tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
+ return false;
+ } // for i - Param
+
+ // All params checked ok
+ return true;
+}
+
+
+
+
+
+bool cLuaState::CheckParamEnd(int a_Param)
+{
+ tolua_Error tolua_err;
+ if (tolua_isnoobj(m_LuaState, a_Param, &tolua_err))
+ {
+ return true;
+ }
+ // Not the correct parameter
+ lua_Debug entry;
+ VERIFY(lua_getstack(m_LuaState, 0, &entry));
+ VERIFY(lua_getinfo (m_LuaState, "n", &entry));
+ AString ErrMsg = Printf("#ferror in function '%s': Too many arguments.", (entry.name != NULL) ? entry.name : "?");
+ tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
+ return false;
+}
+
+
+
+
+
+bool cLuaState::ReportErrors(int a_Status)
+{
+ return ReportErrors(m_LuaState, a_Status);
+}
+
+
+
+
+
+bool cLuaState::ReportErrors(lua_State * a_LuaState, int a_Status)
+{
+ if (a_Status == 0)
+ {
+ // No error to report
+ return false;
+ }
+
+ LOGWARNING("LUA: %d - %s", a_Status, lua_tostring(a_LuaState, -1));
+ lua_pop(a_LuaState, 1);
+ return true;
+}
+
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// cLuaState::cRef:
+
+cLuaState::cRef::cRef(cLuaState & a_LuaState, int a_StackPos) :
+ m_LuaState(a_LuaState)
+{
+ ASSERT(m_LuaState.IsValid());
+
+ lua_pushvalue(m_LuaState, a_StackPos); // Push a copy of the value at a_StackPos onto the stack
+ m_Ref = luaL_ref(m_LuaState, LUA_REGISTRYINDEX);
+}
+
+
+
+
+
+cLuaState::cRef::~cRef()
+{
+ ASSERT(m_LuaState.IsValid());
+
+ if (IsValid())
+ {
+ luaL_unref(m_LuaState, LUA_REGISTRYINDEX, m_Ref);
+ }
+}
+
+
+
+
diff --git a/source/LuaState.h b/source/LuaState.h
new file mode 100644
index 000000000..6820f1777
--- /dev/null
+++ b/source/LuaState.h
@@ -0,0 +1,198 @@
+
+// LuaState.h
+
+// Declares the cLuaState class representing the wrapper over lua_State *, provides associated helper functions
+
+/*
+The contained lua_State can be either owned or attached.
+Owned lua_State is created by calling Create() and the cLuaState automatically closes the state
+Or, lua_State can be attached by calling Attach(), the cLuaState doesn't close such a state
+Attaching a state will automatically close an owned state.
+
+Calling a Lua function is done by pushing the function, either by PushFunction() or PushFunctionFromRegistry(),
+then pushing the arguments (PushString(), PushNumber(), PushUserData() etc.) and finally
+executing CallFunction(). cLuaState automatically keeps track of the number of arguments and the name of the
+function (for logging purposes), which makes the call less error-prone.
+
+Reference management is provided by the cLuaState::cRef class. This is used when you need to hold a reference to
+any Lua object across several function calls; usually this is used for callbacks. The class is RAII-like, with
+automatic resource management.
+*/
+
+
+
+
+#pragma once
+
+extern "C"
+{
+ #include "lauxlib.h"
+}
+
+
+
+
+
+class cWorld;
+class cPlayer;
+class cEntity;
+class cItem;
+class cItems;
+class cClientHandle;
+class cPickup;
+
+
+
+
+
+/// Encapsulates a Lua state and provides some syntactic sugar for common operations
+class cLuaState
+{
+public:
+
+ /// Used for storing references to object in the global registry
+ class cRef
+ {
+ public:
+ /// Creates a reference in the specified LuaState for object at the specified StackPos
+ cRef(cLuaState & a_LuaState, int a_StackPos);
+ ~cRef();
+
+ /// Returns true if the reference is valid
+ bool IsValid(void) const {return (m_Ref != LUA_REFNIL); }
+
+ /// Allows to use this class wherever an int (i. e. ref) is to be used
+ operator int(void) { return m_Ref; }
+
+ protected:
+ cLuaState & m_LuaState;
+ int m_Ref;
+ } ;
+
+
+ /** Creates a new instance. The LuaState is not initialized.
+ a_SubsystemName is used for reporting problems in the console, it is "plugin %s" for plugins,
+ or "LuaScript" for the cLuaScript template
+ */
+ cLuaState(const AString & a_SubsystemName);
+
+ /** Creates a new instance. The a_AttachState is attached.
+ Subsystem name is set to "<attached>".
+ */
+ explicit cLuaState(lua_State * a_AttachState);
+
+ ~cLuaState();
+
+ /// Allows this object to be used in the same way as a lua_State *, for example in the LuaLib functions
+ operator lua_State * (void) { return m_LuaState; }
+
+ /// Creates the m_LuaState, if not closed already. This state will be automatically closed in the destructor
+ void Create(void);
+
+ /// Closes the m_LuaState, if not closed already
+ void Close(void);
+
+ /// Attaches the specified state. Operations will be carried out on this state, but it will not be closed in the destructor
+ void Attach(lua_State * a_State);
+
+ /// Detaches a previously attached state.
+ void Detach(void);
+
+ /// Returns true if the m_LuaState is valid
+ bool IsValid(void) const { return (m_LuaState != NULL); }
+
+ /** Loads the specified file
+ Returns false and logs a warning to the console if not successful (but the LuaState is kept open).
+ m_SubsystemName is displayed in the warning log message.
+ */
+ bool LoadFile(const AString & a_FileName);
+
+ /** Pushes the function of the specified name onto the stack.
+ Returns true if successful.
+ If a_ShouldLogFail is true, logs a warning on failure (incl. m_SubsystemName)
+ */
+ bool PushFunction(const char * a_FunctionName, bool a_ShouldLogFailure = true);
+
+ /** Pushes a function that has been saved into the global registry, identified by a_FnRef.
+ Returns true if successful. Logs a warning on failure
+ */
+ bool PushFunctionFromRegistry(int a_FnRef);
+
+ /** Pushes a function that is stored in a table ref.
+ Returns true if successful, false on failure. Doesn't log failure.
+ */
+ bool PushFunctionFromRefTable(cRef & a_TableRef, const char * a_FnName);
+
+ /// Pushes a string vector, as a table, onto the stack
+ void PushStringVector(const AStringVector & a_Vector);
+
+ /// Pushes a usertype of the specified class type onto the stack
+ void PushUserType(void * a_Object, const char * a_Type);
+
+ /// Pushes an integer onto the stack
+ void PushNumber(int a_Value);
+
+ /// Pushes a double onto the stack
+ void PushNumber(double a_Value);
+
+ /// Pushes a string onto the stack
+ void PushString(const char * a_Value);
+
+ /// Pushes a bool onto the stack
+ void PushBool(bool a_Value);
+
+ // Special family of functions that do PushUserType internally, but require one less parameter
+ void PushObject(cWorld * a_World);
+ void PushObject(cPlayer * a_Player);
+ void PushObject(cEntity * a_Entity);
+ void PushObject(cItem * a_Item);
+ void PushObject(cItems * a_Items);
+ void PushObject(cClientHandle * a_ClientHandle);
+ void PushObject(cPickup * a_Pickup);
+
+ /**
+ Calls the function that has been pushed onto the stack by PushFunction(),
+ with arguments pushed by PushXXX().
+ Returns true if successful, logs a warning on failure.
+ */
+ bool CallFunction(int a_NumReturnValues);
+
+ /// Returns true if the specified parameters on the stack are of the specified usertype; also logs warning if not
+ bool CheckParamUserType(int a_StartParam, const char * a_UserType, int a_EndParam = -1);
+
+ /// Returns true if the specified parameters on the stack are a table; also logs warning if not
+ bool CheckParamTable(int a_StartParam, int a_EndParam = -1);
+
+ /// Returns true if the specified parameters on the stack are a number; also logs warning if not
+ bool CheckParamNumber(int a_StartParam, int a_EndParam = -1);
+
+ /// Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters)
+ bool CheckParamEnd(int a_Param);
+
+ /// If the status is nonzero, prints the text on the top of Lua stack and returns true
+ bool ReportErrors(int status);
+
+ /// If the status is nonzero, prints the text on the top of Lua stack and returns true
+ static bool ReportErrors(lua_State * a_LuaState, int status);
+
+protected:
+ lua_State * m_LuaState;
+
+ /// If true, the state is owned by this object and will be auto-Closed. False => attached state
+ bool m_IsOwned;
+
+ /** The subsystem name is used for reporting errors to the console, it is either "plugin %s" or "LuaScript"
+ whatever is given to the constructor
+ */
+ AString m_SubsystemName;
+
+ /// Name of the currently pushed function (for the Push / Call chain)
+ AString m_CurrentFunctionName;
+
+ /// Number of arguments currently pushed (for the Push / Call chain)
+ int m_NumCurrentFunctionArgs;
+} ;
+
+
+
+
diff --git a/source/ManualBindings.cpp b/source/ManualBindings.cpp
index 9e9b5f5a8..4041ccc94 100644
--- a/source/ManualBindings.cpp
+++ b/source/ManualBindings.cpp
@@ -19,13 +19,8 @@
#include "BlockEntities/FurnaceEntity.h"
#include "md5/md5.h"
#include "LuaWindow.h"
-
-
-
-
-
-// fwd: LuaCommandBinder.cpp
-bool report_errors(lua_State* lua, int status);
+#include "LuaState.h"
+#include "LineBlockTracer.h"
@@ -83,23 +78,14 @@ int lua_do_error(lua_State* L, const char * a_pFormat, ...)
* Lua bound functions with special return types
**/
-static int tolua_StringSplit(lua_State* tolua_S)
+static int tolua_StringSplit(lua_State * tolua_S)
{
- std::string str = ((std::string) tolua_tocppstring(tolua_S,1,0));
- std::string delim = ((std::string) tolua_tocppstring(tolua_S,2,0));
-
- AStringVector Split = StringSplit( str, delim );
+ cLuaState LuaState(tolua_S);
+ std::string str = (std::string)tolua_tocppstring(LuaState, 1, 0);
+ std::string delim = (std::string)tolua_tocppstring(LuaState, 2, 0);
- lua_createtable(tolua_S, Split.size(), 0);
- int newTable = lua_gettop(tolua_S);
- int index = 1;
- std::vector<std::string>::const_iterator iter = Split.begin();
- while(iter != Split.end()) {
- tolua_pushstring( tolua_S, (*iter).c_str() );
- lua_rawseti(tolua_S, newTable, index);
- ++iter;
- ++index;
- }
+ AStringVector Split = StringSplit(str, delim);
+ LuaState.PushStringVector(Split);
return 1;
}
@@ -157,7 +143,8 @@ cPlugin_NewLua * GetLuaPlugin(lua_State * L)
lua_getglobal(L, LUA_PLUGIN_INSTANCE_VAR_NAME);
if (!lua_islightuserdata(L, -1))
{
- LOGERROR("%s: cannot get plugin instance, what have you done to my Lua state?", __FUNCTION__);
+ LOGWARNING("%s: cannot get plugin instance, what have you done to my Lua state?", __FUNCTION__);
+ lua_pop(L, 1);
return NULL;
}
cPlugin_NewLua * Plugin = (cPlugin_NewLua *)lua_topointer(L, -1);
@@ -233,7 +220,7 @@ static int tolua_DoWith(lua_State* tolua_S)
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (report_errors(LuaState, s))
+ if (cLuaState::ReportErrors(LuaState, s))
{
return true; // Abort enumeration
}
@@ -323,7 +310,7 @@ static int tolua_DoWithID(lua_State* tolua_S)
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (report_errors(LuaState, s))
+ if (cLuaState::ReportErrors(LuaState, s))
{
return true; // Abort enumeration
}
@@ -354,9 +341,11 @@ static int tolua_DoWithID(lua_State* tolua_S)
-template< class Ty1,
- class Ty2,
- bool (Ty1::*Func1)(int, int, int, cItemCallback<Ty2> &) >
+template<
+ class Ty1,
+ class Ty2,
+ bool (Ty1::*Func1)(int, int, int, cItemCallback<Ty2> &)
+>
static int tolua_DoWithXYZ(lua_State* tolua_S)
{
int NumArgs = lua_gettop(tolua_S) - 1; /* This includes 'self' */
@@ -418,7 +407,7 @@ static int tolua_DoWithXYZ(lua_State* tolua_S)
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (report_errors(LuaState, s))
+ if (cLuaState::ReportErrors(LuaState, s))
{
return true; // Abort enumeration
}
@@ -511,7 +500,7 @@ static int tolua_ForEachInChunk(lua_State* tolua_S)
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (report_errors(LuaState, s))
+ if (cLuaState::ReportErrors(LuaState, s))
{
return true; /* Abort enumeration */
}
@@ -602,7 +591,7 @@ static int tolua_ForEach(lua_State * tolua_S)
}
int s = lua_pcall(LuaState, (TableRef == LUA_REFNIL ? 1 : 2), 1, 0);
- if (report_errors(LuaState, s))
+ if (cLuaState::ReportErrors(LuaState, s))
{
return true; /* Abort enumeration */
}
@@ -813,7 +802,7 @@ static int tolua_cPluginManager_ForEachCommand(lua_State * tolua_S)
tolua_pushcppstring(LuaState, a_HelpString);
int s = lua_pcall(LuaState, 3, 1, 0);
- if (report_errors(LuaState, s))
+ if (cLuaState::ReportErrors(LuaState, s))
{
return true; /* Abort enumeration */
}
@@ -887,7 +876,7 @@ static int tolua_cPluginManager_ForEachConsoleCommand(lua_State * tolua_S)
tolua_pushcppstring(LuaState, a_HelpString);
int s = lua_pcall(LuaState, 2, 1, 0);
- if (report_errors(LuaState, s))
+ if (cLuaState::ReportErrors(LuaState, s))
{
return true; /* Abort enumeration */
}
@@ -1307,8 +1296,8 @@ static int tolua_cPlugin_Call(lua_State* tolua_S)
return 0;
}
- int s = lua_pcall(targetState, top-2, LUA_MULTRET, 0);
- if( report_errors( targetState, s ) )
+ int s = lua_pcall(targetState, top - 2, LUA_MULTRET, 0);
+ if (cLuaState::ReportErrors(targetState, s))
{
LOGWARN("Error while calling function '%s' in plugin '%s'", funcName.c_str(), self->GetName().c_str() );
return 0;
@@ -1497,9 +1486,174 @@ tolua_lerror:
+/// Provides interface between a Lua table of callbacks and the cBlockTracer::cCallbacks
+class cLuaBlockTracerCallbacks :
+ public cBlockTracer::cCallbacks
+{
+public:
+ cLuaBlockTracerCallbacks(cLuaState & a_LuaState, int a_ParamNum) :
+ m_LuaState(a_LuaState),
+ m_TableRef(a_LuaState, a_ParamNum)
+ {
+ }
+
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
+ {
+ if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlock"))
+ {
+ // No such function in the table, skip the callback
+ return false;
+ }
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockType);
+ m_LuaState.PushNumber(a_BlockMeta);
+ if (!m_LuaState.CallFunction(1))
+ {
+ return false;
+ }
+ bool res = false;
+ if (lua_isboolean(m_LuaState, -1))
+ {
+ res = (lua_toboolean(m_LuaState, -1) != 0);
+ }
+ lua_pop(m_LuaState, 1);
+ return res;
+ }
+
+ virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlockNoData"))
+ {
+ // No such function in the table, skip the callback
+ return false;
+ }
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ if (!m_LuaState.CallFunction(1))
+ {
+ return false;
+ }
+ bool res = false;
+ if (lua_isboolean(m_LuaState, -1))
+ {
+ res = (lua_toboolean(m_LuaState, -1) != 0);
+ }
+ lua_pop(m_LuaState, 1);
+ return res;
+ }
+
+ virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
+ {
+ if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnOutOfWorld"))
+ {
+ // No such function in the table, skip the callback
+ return false;
+ }
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ if (!m_LuaState.CallFunction(1))
+ {
+ return false;
+ }
+ bool res = false;
+ if (lua_isboolean(m_LuaState, -1))
+ {
+ res = (lua_toboolean(m_LuaState, -1) != 0);
+ }
+ lua_pop(m_LuaState, 1);
+ return res;
+ }
+
+ virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
+ {
+ if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnIntoWorld"))
+ {
+ // No such function in the table, skip the callback
+ return false;
+ }
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ if (!m_LuaState.CallFunction(1))
+ {
+ return false;
+ }
+ bool res = false;
+ if (lua_isboolean(m_LuaState, -1))
+ {
+ res = (lua_toboolean(m_LuaState, -1) != 0);
+ }
+ lua_pop(m_LuaState, 1);
+ return res;
+ }
+
+ virtual void OnNoMoreHits(void) override
+ {
+ if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNoMoreHits"))
+ {
+ // No such function in the table, skip the callback
+ return;
+ }
+ m_LuaState.CallFunction(0);
+ }
+
+ virtual void OnNoChunk(void) override
+ {
+ if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNoChunk"))
+ {
+ // No such function in the table, skip the callback
+ return;
+ }
+ m_LuaState.CallFunction(0);
+ }
+
+protected:
+ cLuaState & m_LuaState;
+ cLuaState::cRef m_TableRef;
+} ;
+
+
+
+
+
+static int tolua_cLineBlockTracer_Trace(lua_State * tolua_S)
+{
+ // cLineBlockTracer.Trace(World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ)
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamUserType(1, "cWorld") ||
+ !L.CheckParamTable (2) ||
+ !L.CheckParamNumber (3, 8) ||
+ !L.CheckParamEnd (9)
+ )
+ {
+ return 0;
+ }
+
+ cWorld * World = (cWorld *)tolua_tousertype(L, 1, NULL);
+ cLuaBlockTracerCallbacks Callbacks(L, 2);
+ double StartX = tolua_tonumber(L, 3, 0);
+ double StartY = tolua_tonumber(L, 4, 0);
+ double StartZ = tolua_tonumber(L, 5, 0);
+ double EndX = tolua_tonumber(L, 6, 0);
+ double EndY = tolua_tonumber(L, 7, 0);
+ double EndZ = tolua_tonumber(L, 8, 0);
+ bool res = cLineBlockTracer::Trace(*World, Callbacks, StartX, StartY, StartZ, EndX, EndY, EndZ);
+ tolua_pushboolean(L, res ? 1 : 0);
+ return 1;
+}
+
+
+
+
+
void ManualBindings::Bind(lua_State * tolua_S)
{
- tolua_beginmodule(tolua_S,NULL);
+ tolua_beginmodule(tolua_S, NULL);
tolua_function(tolua_S, "StringSplit", tolua_StringSplit);
tolua_function(tolua_S, "LOG", tolua_LOG);
tolua_function(tolua_S, "LOGINFO", tolua_LOGINFO);
@@ -1507,6 +1661,10 @@ void ManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "LOGWARNING", tolua_LOGWARN);
tolua_function(tolua_S, "LOGERROR", tolua_LOGERROR);
+ tolua_beginmodule(tolua_S, "cLineBlockTracer");
+ tolua_function(tolua_S, "Trace", tolua_cLineBlockTracer_Trace);
+ tolua_endmodule(tolua_S);
+
tolua_beginmodule(tolua_S, "cRoot");
tolua_function(tolua_S, "FindAndDoWithPlayer", tolua_DoWith <cRoot, cPlayer, &cRoot::FindAndDoWithPlayer>);
tolua_function(tolua_S, "ForEachPlayer", tolua_ForEach<cRoot, cPlayer, &cRoot::ForEachPlayer>);
diff --git a/source/Plugin_NewLua.cpp b/source/Plugin_NewLua.cpp
index 8b0f047cd..704bb3a95 100644
--- a/source/Plugin_NewLua.cpp
+++ b/source/Plugin_NewLua.cpp
@@ -7,45 +7,10 @@
extern "C"
{
-#include "lualib.h"
+ #include "lualib.h"
}
#include "tolua++.h"
-#include "Bindings.h"
-#include "ManualBindings.h"
-
-
-
-
-
-// fwd: SQLite/lsqlite3.c
-extern "C"
-{
- LUALIB_API int luaopen_lsqlite3(lua_State * L);
-}
-
-// fwd: LuaExpat/lxplib.c:
-extern "C"
-{
- int luaopen_lxp(lua_State * L);
-}
-
-
-
-
-
-bool report_errors(lua_State * lua, int status)
-{
- if (status == 0)
- {
- // No error to report
- return false;
- }
-
- LOGERROR("LUA: %s", lua_tostring(lua, -1));
- lua_pop(lua, 1);
- return true;
-}
@@ -54,10 +19,9 @@ bool report_errors(lua_State * lua, int status)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cPlugin_NewLua:
-cPlugin_NewLua::cPlugin_NewLua(const AString & a_PluginDirectory)
- : m_LuaState( 0 )
- , cWebPlugin()
- , cPlugin(a_PluginDirectory)
+cPlugin_NewLua::cPlugin_NewLua(const AString & a_PluginDirectory) :
+ cPlugin(a_PluginDirectory),
+ m_LuaState(Printf("plugin %s", a_PluginDirectory.c_str()))
{
}
@@ -68,12 +32,7 @@ cPlugin_NewLua::cPlugin_NewLua(const AString & a_PluginDirectory)
cPlugin_NewLua::~cPlugin_NewLua()
{
cCSLock Lock(m_CriticalSection);
-
- if( m_LuaState )
- {
- lua_close( m_LuaState );
- m_LuaState = 0;
- }
+ m_LuaState.Close();
}
@@ -83,14 +42,9 @@ cPlugin_NewLua::~cPlugin_NewLua()
bool cPlugin_NewLua::Initialize(void)
{
cCSLock Lock(m_CriticalSection);
- if (m_LuaState == NULL)
+ if (!m_LuaState.IsValid())
{
- m_LuaState = lua_open();
- luaL_openlibs(m_LuaState);
- tolua_AllToLua_open(m_LuaState);
- ManualBindings::Bind(m_LuaState);
- luaopen_lsqlite3(m_LuaState);
- luaopen_lxp(m_LuaState);
+ m_LuaState.Create();
// Inject the identification global variables into the state:
lua_pushlightuserdata(m_LuaState, this);
@@ -110,47 +64,32 @@ bool cPlugin_NewLua::Initialize(void)
continue;
}
AString Path = PluginPath + *itr;
- int s = luaL_loadfile(m_LuaState, Path.c_str() );
- if( report_errors( m_LuaState, s ) )
+ if (!m_LuaState.LoadFile(Path))
{
- LOGERROR("Can't load plugin %s because of an error in file %s", GetLocalDirectory().c_str(), Path.c_str() );
- lua_close( m_LuaState );
- m_LuaState = 0;
- return false;
- }
-
- s = lua_pcall(m_LuaState, 0, LUA_MULTRET, 0);
- if( report_errors( m_LuaState, s ) )
- {
- LOGERROR("Error in plugin %s in file %s", GetLocalDirectory().c_str(), Path.c_str() );
- lua_close( m_LuaState );
- m_LuaState = 0;
+ m_LuaState.Close();
return false;
}
} // for itr - Files[]
// Call intialize function
- if (!PushFunction("Initialize"))
+ if (!m_LuaState.PushFunction("Initialize"))
{
- lua_close( m_LuaState );
- m_LuaState = 0;
+ m_LuaState.Close();
return false;
}
- tolua_pushusertype(m_LuaState, this, "cPlugin_NewLua");
+ m_LuaState.PushUserType(this, "cPlugin_NewLua");
- if (!CallFunction(1, 1, "Initialize"))
+ if (!m_LuaState.CallFunction(1))
{
- lua_close( m_LuaState );
- m_LuaState = 0;
+ m_LuaState.Close();
return false;
}
- if( !lua_isboolean( m_LuaState, -1 ) )
+ if (!lua_isboolean(m_LuaState, -1))
{
- LOGWARN("Error in plugin %s Initialize() must return a boolean value!", GetLocalDirectory().c_str() );
- lua_close( m_LuaState );
- m_LuaState = 0;
+ LOGWARNING("Error in plugin %s: Initialize() must return a boolean value!", GetName().c_str());
+ m_LuaState.Close();
return false;
}
@@ -165,12 +104,12 @@ bool cPlugin_NewLua::Initialize(void)
void cPlugin_NewLua::OnDisable()
{
cCSLock Lock(m_CriticalSection);
- if (!PushFunction("OnDisable", false)) // false = don't log error if not found
+ if (!m_LuaState.PushFunction("OnDisable", false)) // false = don't log error if not found
{
return;
}
- CallFunction(0, 0, "OnDisable");
+ m_LuaState.CallFunction(0);
}
@@ -181,14 +120,12 @@ void cPlugin_NewLua::Tick(float a_Dt)
{
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_TICK);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return;
}
-
- tolua_pushnumber( m_LuaState, a_Dt );
-
- CallFunction(1, 0, FnName);
+ m_LuaState.PushNumber(a_Dt);
+ m_LuaState.CallFunction(0);
}
@@ -200,21 +137,21 @@ bool cPlugin_NewLua::OnBlockToPickups(cWorld * a_World, cEntity * a_Digger, int
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_BLOCK_TO_PICKUPS);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_World, "cWorld");
- tolua_pushusertype(m_LuaState, a_Digger, "cEntity");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockType);
- tolua_pushnumber (m_LuaState, a_BlockMeta);
- tolua_pushusertype(m_LuaState, &a_Pickups, "cItems");
+ m_LuaState.PushObject(a_World);
+ m_LuaState.PushObject(a_Digger);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockType);
+ m_LuaState.PushNumber(a_BlockMeta);
+ m_LuaState.PushObject(&a_Pickups);
- if (!CallFunction(8, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -233,15 +170,15 @@ bool cPlugin_NewLua::OnChat(cPlayer * a_Player, AString & a_Message)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_CHAT);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
- tolua_pushstring (m_LuaState, a_Message.c_str());
+ m_LuaState.PushObject(a_Player);
+ m_LuaState.PushString(a_Message.c_str());
- if (!CallFunction(2, 2, FnName))
+ if (!m_LuaState.CallFunction(2))
{
return false;
}
@@ -264,16 +201,16 @@ bool cPlugin_NewLua::OnChunkAvailable(cWorld * a_World, int a_ChunkX, int a_Chun
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_AVAILABLE);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_World, "cWorld");
- tolua_pushnumber (m_LuaState, a_ChunkX);
- tolua_pushnumber (m_LuaState, a_ChunkZ);
+ m_LuaState.PushObject(a_World);
+ m_LuaState.PushNumber(a_ChunkX);
+ m_LuaState.PushNumber(a_ChunkZ);
- if (!CallFunction(3, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -292,17 +229,17 @@ bool cPlugin_NewLua::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_Chun
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_GENERATED);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_World, "cWorld");
- tolua_pushnumber (m_LuaState, a_ChunkX);
- tolua_pushnumber (m_LuaState, a_ChunkZ);
- tolua_pushusertype(m_LuaState, a_ChunkDesc, "cChunkDesc");
+ m_LuaState.PushObject(a_World);
+ m_LuaState.PushNumber(a_ChunkX);
+ m_LuaState.PushNumber(a_ChunkZ);
+ m_LuaState.PushUserType(a_ChunkDesc, "cChunkDesc");
- if (!CallFunction(4, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -316,22 +253,22 @@ bool cPlugin_NewLua::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_Chun
-bool cPlugin_NewLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_pLuaChunk)
+bool cPlugin_NewLua::OnChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cChunkDesc * a_ChunkDesc)
{
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_GENERATING);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_World, "cWorld");
- tolua_pushnumber (m_LuaState, a_ChunkX);
- tolua_pushnumber (m_LuaState, a_ChunkZ);
- tolua_pushusertype(m_LuaState, a_pLuaChunk, "cChunkDesc");
+ m_LuaState.PushObject(a_World);
+ m_LuaState.PushNumber(a_ChunkX);
+ m_LuaState.PushNumber(a_ChunkZ);
+ m_LuaState.PushUserType(a_ChunkDesc, "cChunkDesc");
- if (!CallFunction(4, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -350,16 +287,16 @@ bool cPlugin_NewLua::OnChunkUnloaded(cWorld * a_World, int a_ChunkX, int a_Chunk
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_UNLOADED);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_World, "cWorld");
- tolua_pushnumber (m_LuaState, a_ChunkX);
- tolua_pushnumber (m_LuaState, a_ChunkZ);
+ m_LuaState.PushObject(a_World);
+ m_LuaState.PushNumber(a_ChunkX);
+ m_LuaState.PushNumber(a_ChunkZ);
- if (!CallFunction(3, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -378,16 +315,16 @@ bool cPlugin_NewLua::OnChunkUnloading(cWorld * a_World, int a_ChunkX, int a_Chun
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_CHUNK_UNLOADING);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_World, "cWorld");
- tolua_pushnumber (m_LuaState, a_ChunkX);
- tolua_pushnumber (m_LuaState, a_ChunkZ);
+ m_LuaState.PushObject(a_World);
+ m_LuaState.PushNumber(a_ChunkX);
+ m_LuaState.PushNumber(a_ChunkZ);
- if (!CallFunction(3, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -406,15 +343,15 @@ bool cPlugin_NewLua::OnCollectingPickup(cPlayer * a_Player, cPickup * a_Pickup)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_COLLECTING_PICKUP);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
- tolua_pushusertype(m_LuaState, a_Pickup, "cPickup");
+ m_LuaState.PushObject(a_Player);
+ m_LuaState.PushObject(a_Pickup);
- if (!CallFunction(2, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -433,16 +370,16 @@ bool cPlugin_NewLua::OnCraftingNoRecipe(const cPlayer * a_Player, const cCraftin
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_CRAFTING_NO_RECIPE);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer");
- tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid");
- tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe");
+ m_LuaState.PushUserType((void *)a_Player, "cPlayer");
+ m_LuaState.PushUserType((void *)a_Grid, "cCraftingGrid");
+ m_LuaState.PushUserType((void *)a_Recipe, "cCraftingRecipe");
- if (!CallFunction(3, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -461,15 +398,15 @@ bool cPlugin_NewLua::OnDisconnect(cPlayer * a_Player, const AString & a_Reason)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_DISCONNECT);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
- tolua_pushstring (m_LuaState, a_Reason.c_str());
+ m_LuaState.PushObject(a_Player);
+ m_LuaState.PushString(a_Reason.c_str());
- if (!CallFunction(2, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -488,27 +425,15 @@ bool cPlugin_NewLua::OnExecuteCommand(cPlayer * a_Player, const AStringVector &
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_EXECUTE_COMMAND);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
-
- // Push the split:
- lua_createtable(m_LuaState, a_Split.size(), 0);
- int newTable = lua_gettop(m_LuaState);
- int index = 1;
- std::vector<std::string>::const_iterator iter = a_Split.begin(), end = a_Split.end();
- while(iter != end)
- {
- tolua_pushstring(m_LuaState, (*iter).c_str());
- lua_rawseti(m_LuaState, newTable, index);
- ++iter;
- ++index;
- }
+ m_LuaState.PushObject(a_Player);
+ m_LuaState.PushStringVector(a_Split);
- if (!CallFunction(2, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -527,15 +452,15 @@ bool cPlugin_NewLua::OnHandshake(cClientHandle * a_Client, const AString & a_Use
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_HANDSHAKE);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, a_Client, "cClientHandle");
- tolua_pushstring (m_LuaState, a_Username.c_str());
+ m_LuaState.PushUserType(a_Client, "cClientHandle");
+ m_LuaState.PushString (a_Username.c_str());
- if (!CallFunction(2, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -554,15 +479,15 @@ bool cPlugin_NewLua::OnKilling(cEntity & a_Victim, cEntity * a_Killer)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_KILLING);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Victim, "cEntity");
- tolua_pushusertype(m_LuaState, a_Killer, "cEntity");
+ m_LuaState.PushObject(&a_Victim);
+ m_LuaState.PushObject(a_Killer);
- if (!CallFunction(2, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -581,16 +506,16 @@ bool cPlugin_NewLua::OnLogin(cClientHandle * a_Client, int a_ProtocolVersion, co
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_LOGIN);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype (m_LuaState, a_Client, "cClientHandle");
- tolua_pushnumber (m_LuaState, a_ProtocolVersion);
- tolua_pushcppstring(m_LuaState, a_Username);
+ m_LuaState.PushObject(a_Client);
+ m_LuaState.PushNumber(a_ProtocolVersion);
+ m_LuaState.PushString(a_Username.c_str());
- if (!CallFunction(3, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -609,20 +534,20 @@ bool cPlugin_NewLua::OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_BREAKING_BLOCK);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_BlockType);
- tolua_pushnumber (m_LuaState, a_BlockMeta);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_BlockType);
+ m_LuaState.PushNumber(a_BlockMeta);
- if (!CallFunction(7, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -641,20 +566,20 @@ bool cPlugin_NewLua::OnPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_BROKEN_BLOCK);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_BlockType);
- tolua_pushnumber (m_LuaState, a_BlockMeta);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_BlockType);
+ m_LuaState.PushNumber(a_BlockMeta);
- if (!CallFunction(7, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -673,14 +598,14 @@ bool cPlugin_NewLua::OnPlayerEating(cPlayer & a_Player)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_EATING);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
+ m_LuaState.PushObject(&a_Player);
- if (!CallFunction(1, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -699,14 +624,14 @@ bool cPlugin_NewLua::OnPlayerJoined(cPlayer & a_Player)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_JOINED);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
+ m_LuaState.PushObject(&a_Player);
- if (!CallFunction(1, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -725,19 +650,19 @@ bool cPlugin_NewLua::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_B
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_LEFT_CLICK);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_Status);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_Status);
- if (!CallFunction(6, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -756,14 +681,14 @@ bool cPlugin_NewLua::OnPlayerMoved(cPlayer & a_Player)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_MOVING);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
+ m_LuaState.PushObject(&a_Player);
- if (!CallFunction(1, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -782,23 +707,23 @@ bool cPlugin_NewLua::OnPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_PLACED_BLOCK);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_CursorX);
- tolua_pushnumber (m_LuaState, a_CursorY);
- tolua_pushnumber (m_LuaState, a_CursorZ);
- tolua_pushnumber (m_LuaState, a_BlockType);
- tolua_pushnumber (m_LuaState, a_BlockMeta);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_CursorX);
+ m_LuaState.PushNumber(a_CursorY);
+ m_LuaState.PushNumber(a_CursorZ);
+ m_LuaState.PushNumber(a_BlockType);
+ m_LuaState.PushNumber(a_BlockMeta);
- if (!CallFunction(10, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -817,23 +742,23 @@ bool cPlugin_NewLua::OnPlayerPlacingBlock(cPlayer & a_Player, int a_BlockX, int
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_PLACING_BLOCK);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_CursorX);
- tolua_pushnumber (m_LuaState, a_CursorY);
- tolua_pushnumber (m_LuaState, a_CursorZ);
- tolua_pushnumber (m_LuaState, a_BlockType);
- tolua_pushnumber (m_LuaState, a_BlockMeta);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_CursorX);
+ m_LuaState.PushNumber(a_CursorY);
+ m_LuaState.PushNumber(a_CursorZ);
+ m_LuaState.PushNumber(a_BlockType);
+ m_LuaState.PushNumber(a_BlockMeta);
- if (!CallFunction(10, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -852,21 +777,21 @@ bool cPlugin_NewLua::OnPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_RIGHT_CLICK);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_CursorX);
- tolua_pushnumber (m_LuaState, a_CursorY);
- tolua_pushnumber (m_LuaState, a_CursorZ);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_CursorX);
+ m_LuaState.PushNumber(a_CursorY);
+ m_LuaState.PushNumber(a_CursorZ);
- if (!CallFunction(8, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -885,15 +810,15 @@ bool cPlugin_NewLua::OnPlayerRightClickingEntity(cPlayer & a_Player, cEntity & a
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_RIGHT_CLICKING_ENTITY);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushusertype(m_LuaState, &a_Entity, "cEntity");
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushObject(&a_Entity);
- if (!CallFunction(2, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -912,14 +837,14 @@ bool cPlugin_NewLua::OnPlayerShooting(cPlayer & a_Player)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_SHOOTING);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
+ m_LuaState.PushObject(&a_Player);
- if (!CallFunction(1, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -938,14 +863,14 @@ bool cPlugin_NewLua::OnPlayerSpawned(cPlayer & a_Player)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_SPAWNED);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
+ m_LuaState.PushObject(&a_Player);
- if (!CallFunction(1, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -964,14 +889,14 @@ bool cPlugin_NewLua::OnPlayerTossingItem(cPlayer & a_Player)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_TOSSING_ITEM);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
+ m_LuaState.PushObject(&a_Player);
- if (!CallFunction(1, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -990,23 +915,23 @@ bool cPlugin_NewLua::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_B
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_USED_BLOCK);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_CursorX);
- tolua_pushnumber (m_LuaState, a_CursorY);
- tolua_pushnumber (m_LuaState, a_CursorZ);
- tolua_pushnumber (m_LuaState, a_BlockType);
- tolua_pushnumber (m_LuaState, a_BlockMeta);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_CursorX);
+ m_LuaState.PushNumber(a_CursorY);
+ m_LuaState.PushNumber(a_CursorZ);
+ m_LuaState.PushNumber(a_BlockType);
+ m_LuaState.PushNumber(a_BlockMeta);
- if (!CallFunction(10, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -1025,21 +950,21 @@ bool cPlugin_NewLua::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_Bl
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_USED_ITEM);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_CursorX);
- tolua_pushnumber (m_LuaState, a_CursorY);
- tolua_pushnumber (m_LuaState, a_CursorZ);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_CursorX);
+ m_LuaState.PushNumber(a_CursorY);
+ m_LuaState.PushNumber(a_CursorZ);
- if (!CallFunction(8, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -1058,23 +983,23 @@ bool cPlugin_NewLua::OnPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_USING_BLOCK);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_CursorX);
- tolua_pushnumber (m_LuaState, a_CursorY);
- tolua_pushnumber (m_LuaState, a_CursorZ);
- tolua_pushnumber (m_LuaState, a_BlockType);
- tolua_pushnumber (m_LuaState, a_BlockMeta);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_CursorX);
+ m_LuaState.PushNumber(a_CursorY);
+ m_LuaState.PushNumber(a_CursorZ);
+ m_LuaState.PushNumber(a_BlockType);
+ m_LuaState.PushNumber(a_BlockMeta);
- if (!CallFunction(10, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -1093,21 +1018,21 @@ bool cPlugin_NewLua::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_B
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PLAYER_USING_ITEM);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushnumber (m_LuaState, a_BlockFace);
- tolua_pushnumber (m_LuaState, a_CursorX);
- tolua_pushnumber (m_LuaState, a_CursorY);
- tolua_pushnumber (m_LuaState, a_CursorZ);
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushNumber(a_BlockFace);
+ m_LuaState.PushNumber(a_CursorX);
+ m_LuaState.PushNumber(a_CursorY);
+ m_LuaState.PushNumber(a_CursorZ);
- if (!CallFunction(8, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -1126,16 +1051,16 @@ bool cPlugin_NewLua::OnPostCrafting(const cPlayer * a_Player, const cCraftingGri
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_POST_CRAFTING);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer");
- tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid");
- tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe");
+ m_LuaState.PushUserType((void *)a_Player, "cPlayer");
+ m_LuaState.PushUserType((void *)a_Grid, "cCraftingGrid");
+ m_LuaState.PushUserType((void *)a_Recipe, "cCraftingRecipe");
- if (!CallFunction(3, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -1154,16 +1079,16 @@ bool cPlugin_NewLua::OnPreCrafting(const cPlayer * a_Player, const cCraftingGrid
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_PRE_CRAFTING);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer");
- tolua_pushusertype(m_LuaState, (void *)a_Grid, "cCraftingGrid");
- tolua_pushusertype(m_LuaState, (void *)a_Recipe, "cCraftingRecipe");
+ m_LuaState.PushUserType((void *)a_Player, "cPlayer");
+ m_LuaState.PushUserType((void *)a_Grid, "cCraftingGrid");
+ m_LuaState.PushUserType((void *)a_Recipe, "cCraftingRecipe");
- if (!CallFunction(3, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -1182,15 +1107,15 @@ bool cPlugin_NewLua::OnTakeDamage(cEntity & a_Receiver, TakeDamageInfo & a_TDI)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_TAKE_DAMAGE);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_Receiver, "cEntity");
- tolua_pushusertype(m_LuaState, &a_TDI, "TakeDamageInfo");
+ m_LuaState.PushObject(&a_Receiver);
+ m_LuaState.PushUserType(&a_TDI, "TakeDamageInfo");
- if (!CallFunction(2, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -1214,22 +1139,22 @@ bool cPlugin_NewLua::OnUpdatedSign(
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_UPDATED_SIGN);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, (void *)a_World, "cWorld");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushstring (m_LuaState, a_Line1.c_str());
- tolua_pushstring (m_LuaState, a_Line2.c_str());
- tolua_pushstring (m_LuaState, a_Line3.c_str());
- tolua_pushstring (m_LuaState, a_Line4.c_str());
- tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer");
+ m_LuaState.PushObject(a_World);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushString(a_Line1.c_str());
+ m_LuaState.PushString(a_Line2.c_str());
+ m_LuaState.PushString(a_Line3.c_str());
+ m_LuaState.PushString(a_Line4.c_str());
+ m_LuaState.PushObject(a_Player);
- if (!CallFunction(9, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -1253,22 +1178,22 @@ bool cPlugin_NewLua::OnUpdatingSign(
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_UPDATING_SIGN);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, (void *)a_World, "cWorld");
- tolua_pushnumber (m_LuaState, a_BlockX);
- tolua_pushnumber (m_LuaState, a_BlockY);
- tolua_pushnumber (m_LuaState, a_BlockZ);
- tolua_pushstring (m_LuaState, a_Line1.c_str());
- tolua_pushstring (m_LuaState, a_Line2.c_str());
- tolua_pushstring (m_LuaState, a_Line3.c_str());
- tolua_pushstring (m_LuaState, a_Line4.c_str());
- tolua_pushusertype(m_LuaState, (void *)a_Player, "cPlayer");
+ m_LuaState.PushObject(a_World);
+ m_LuaState.PushNumber(a_BlockX);
+ m_LuaState.PushNumber(a_BlockY);
+ m_LuaState.PushNumber(a_BlockZ);
+ m_LuaState.PushString(a_Line1.c_str());
+ m_LuaState.PushString(a_Line2.c_str());
+ m_LuaState.PushString(a_Line3.c_str());
+ m_LuaState.PushString(a_Line4.c_str());
+ m_LuaState.PushObject(a_Player);
- if (!CallFunction(9, 5, "OnUpdatingSign"))
+ if (!m_LuaState.CallFunction(5))
{
return false;
}
@@ -1303,14 +1228,14 @@ bool cPlugin_NewLua::OnWeatherChanged(cWorld & a_World)
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_WEATHER_CHANGED);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_World, "cWorld");
+ m_LuaState.PushObject(&a_World);
- if (!CallFunction(1, 1, FnName))
+ if (!m_LuaState.CallFunction(1))
{
return false;
}
@@ -1329,15 +1254,15 @@ bool cPlugin_NewLua::OnWeatherChanging(cWorld & a_World, eWeather & a_NewWeather
cCSLock Lock(m_CriticalSection);
const char * FnName = GetHookFnName(cPluginManager::HOOK_WEATHER_CHANGED);
ASSERT(FnName != NULL);
- if (!PushFunction(FnName))
+ if (!m_LuaState.PushFunction(FnName))
{
return false;
}
- tolua_pushusertype(m_LuaState, &a_World, "cWorld");
- tolua_pushnumber (m_LuaState, a_NewWeather);
+ m_LuaState.PushObject(&a_World);
+ m_LuaState.PushNumber(a_NewWeather);
- if (!CallFunction(2, 2, FnName))
+ if (!m_LuaState.CallFunction(2))
{
return false;
}
@@ -1368,29 +1293,19 @@ bool cPlugin_NewLua::HandleCommand(const AStringVector & a_Split, cPlayer * a_Pl
cCSLock Lock(m_CriticalSection);
// Push the function to be called:
- lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref()
-
- // Push the split:
- lua_createtable(m_LuaState, a_Split.size(), 0);
- int newTable = lua_gettop(m_LuaState);
- int index = 1;
- std::vector<std::string>::const_iterator iter = a_Split.begin(), end = a_Split.end();
- while(iter != end)
- {
- tolua_pushstring(m_LuaState, (*iter).c_str());
- lua_rawseti(m_LuaState, newTable, index);
- ++iter;
- ++index;
+ if (!m_LuaState.PushFunctionFromRegistry(cmd->second))
+ {
+ LOGWARNING("Command handler function for \"%s\" is invalid", cmd->first.c_str());
+ return false;
}
- // Push player:
- tolua_pushusertype(m_LuaState, a_Player, "cPlayer");
+ m_LuaState.PushStringVector(a_Split);
+ m_LuaState.PushObject(a_Player);
// Call function:
- int s = lua_pcall(m_LuaState, 2, 1, 0);
- if (report_errors(m_LuaState, s))
+ if (!m_LuaState.CallFunction(1))
{
- LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
+ LOGWARNING("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
return false;
}
@@ -1420,26 +1335,14 @@ bool cPlugin_NewLua::HandleConsoleCommand(const AStringVector & a_Split, cComman
cCSLock Lock(m_CriticalSection);
// Push the function to be called:
- lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, cmd->second); // same as lua_getref()
+ m_LuaState.PushFunctionFromRegistry(cmd->second);
- // Push the split:
- lua_createtable(m_LuaState, a_Split.size(), 0);
- int newTable = lua_gettop(m_LuaState);
- int index = 1;
- std::vector<std::string>::const_iterator iter = a_Split.begin(), end = a_Split.end();
- while(iter != end)
- {
- tolua_pushstring(m_LuaState, (*iter).c_str());
- lua_rawseti(m_LuaState, newTable, index);
- ++iter;
- ++index;
- }
+ m_LuaState.PushStringVector(a_Split);
// Call function:
- int s = lua_pcall(m_LuaState, 1, 2, 0);
- if (report_errors(m_LuaState, s))
+ if (!m_LuaState.CallFunction(2))
{
- LOGERROR("Lua error. Stack size: %i", lua_gettop(m_LuaState));
+ LOGWARNING("Lua error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
return false;
}
@@ -1604,9 +1507,9 @@ AString cPlugin_NewLua::HandleWebRequest(const HTTPRequest * a_Request )
return "";
sWebPluginTab* Tab = 0;
- for( TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr )
+ for (TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr)
{
- if( (*itr)->SafeTitle.compare( SafeTabName ) == 0 ) // This is the one! Rawr
+ if ((*itr)->SafeTitle.compare(SafeTabName) == 0) // This is the one! Rawr
{
Tab = *itr;
break;
@@ -1615,34 +1518,26 @@ AString cPlugin_NewLua::HandleWebRequest(const HTTPRequest * a_Request )
if( Tab )
{
- //LOGINFO("1. Stack size: %i", lua_gettop(m_LuaState) );
- lua_rawgeti( m_LuaState, LUA_REGISTRYINDEX, Tab->UserData); // same as lua_getref()
+ m_LuaState.PushFunctionFromRegistry(Tab->UserData);
- //LOGINFO("2. Stack size: %i", lua_gettop(m_LuaState) );
// Push HTTPRequest
- tolua_pushusertype( m_LuaState, (void*)a_Request, "const HTTPRequest" );
- //LOGINFO("Calling bound function! :D");
- int s = lua_pcall( m_LuaState, 1, 1, 0);
-
- if ( s != 0 )
+ m_LuaState.PushUserType((void*)a_Request, "const HTTPRequest");
+
+ if (!m_LuaState.CallFunction(1))
{
- std::string err = lua_tostring(m_LuaState, -1);
- LOGERROR("-- %s", err.c_str() );
- lua_pop(m_LuaState, 1);
- LOGINFO("error. Stack size: %i", lua_gettop(m_LuaState) );
- return err; // Show the error message in the web page, looks cool
+ return "Lua encountered error while processing the page request";
}
- if( !lua_isstring( m_LuaState, -1 ) )
+ if (!lua_isstring(m_LuaState, -1))
{
- LOGWARN("WARNING: WebPlugin tab '%s' did not return a string!", Tab->Title.c_str() );
- lua_pop(m_LuaState, 1); // Pop return value
- return std::string("WARNING: WebPlugin tab '") + Tab->Title + std::string("' did not return a string!");
+ LOGWARNING("WebPlugin tab '%s' did not return a string!", Tab->Title.c_str());
+ lua_pop(m_LuaState, 1); // Pop return value
+ return Printf("WARNING: WebPlugin tab '%s' did not return a string!", Tab->Title.c_str());
}
RetVal += tolua_tostring(m_LuaState, -1, 0);
lua_pop(m_LuaState, 1); // Pop return value
- //LOGINFO("ok. Stack size: %i", lua_gettop(m_LuaState) );
+ // LOGINFO("ok. Stack size: %i", lua_gettop(m_LuaState) );
}
return RetVal;
@@ -1652,7 +1547,7 @@ AString cPlugin_NewLua::HandleWebRequest(const HTTPRequest * a_Request )
-bool cPlugin_NewLua::AddWebTab( const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference )
+bool cPlugin_NewLua::AddWebTab(const AString & a_Title, lua_State * a_LuaState, int a_FunctionReference)
{
cCSLock Lock(m_CriticalSection);
if (a_LuaState != m_LuaState)
@@ -1666,7 +1561,7 @@ bool cPlugin_NewLua::AddWebTab( const AString & a_Title, lua_State * a_LuaState,
Tab->UserData = a_FunctionReference;
- GetTabs().push_back( Tab );
+ GetTabs().push_back(Tab);
return true;
}
@@ -1709,16 +1604,15 @@ bool cPlugin_NewLua::CallbackWindowClosing(int a_FnRef, cWindow & a_Window, cPla
ASSERT(a_FnRef != LUA_REFNIL);
cCSLock Lock(m_CriticalSection);
- lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // Push the function to be called
- tolua_pushusertype(m_LuaState, &a_Window, "cWindow");
- tolua_pushusertype(m_LuaState, &a_Player, "cPlayer");
- tolua_pushboolean (m_LuaState, a_CanRefuse ? 1 : 0);
+ m_LuaState.PushFunctionFromRegistry(a_FnRef);
+ m_LuaState.PushUserType(&a_Window, "cWindow");
+ m_LuaState.PushObject(&a_Player);
+ m_LuaState.PushBool(a_CanRefuse);
// Call function:
- int s = lua_pcall(m_LuaState, 3, 1, 0);
- if (report_errors(m_LuaState, s))
+ if (!m_LuaState.CallFunction(1))
{
- LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
+ LOGWARNING("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
return false;
}
@@ -1736,59 +1630,15 @@ void cPlugin_NewLua::CallbackWindowSlotChanged(int a_FnRef, cWindow & a_Window,
ASSERT(a_FnRef != LUA_REFNIL);
cCSLock Lock(m_CriticalSection);
- lua_rawgeti(m_LuaState, LUA_REGISTRYINDEX, a_FnRef); // Push the function to be called
- tolua_pushusertype(m_LuaState, &a_Window, "cWindow");
- tolua_pushnumber (m_LuaState, a_SlotNum);
+ m_LuaState.PushFunctionFromRegistry(a_FnRef);
+ m_LuaState.PushUserType(&a_Window, "cWindow");
+ m_LuaState.PushNumber(a_SlotNum);
// Call function:
- int s = lua_pcall(m_LuaState, 2, 0, 0);
- if (report_errors(m_LuaState, s))
- {
- LOGERROR("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
- }
-}
-
-
-
-
-
-// Helper functions
-bool cPlugin_NewLua::PushFunction(const char * a_FunctionName, bool a_bLogError /* = true */)
-{
- if (m_LuaState == NULL)
+ if (!m_LuaState.CallFunction(0))
{
- // This happens if Initialize() fails with an error
- return false;
+ LOGWARNING("LUA error in %s. Stack size: %i", __FUNCTION__, lua_gettop(m_LuaState));
}
-
- lua_getglobal(m_LuaState, a_FunctionName);
- if (!lua_isfunction(m_LuaState, -1))
- {
- if (a_bLogError)
- {
- LOGWARN("Error in plugin %s: Could not find function %s()", GetName().c_str(), a_FunctionName);
- }
- lua_pop(m_LuaState, 1);
- return false;
- }
- return true;
-}
-
-
-
-
-
-bool cPlugin_NewLua::CallFunction( int a_NumArgs, int a_NumResults, const char * a_FunctionName)
-{
- ASSERT(lua_isfunction(m_LuaState, -a_NumArgs - 1));
-
- int s = lua_pcall(m_LuaState, a_NumArgs, a_NumResults, 0);
- if (report_errors(m_LuaState, s))
- {
- LOGWARN("Error in plugin %s calling function %s()", GetName().c_str(), a_FunctionName);
- return false;
- }
- return true;
}
diff --git a/source/Plugin_NewLua.h b/source/Plugin_NewLua.h
index a79affd5d..d31a62601 100644
--- a/source/Plugin_NewLua.h
+++ b/source/Plugin_NewLua.h
@@ -3,6 +3,7 @@
#include "Plugin.h"
#include "WebPlugin.h"
+#include "LuaState.h"
// Names for the global variables through which the plugin is identified in its LuaState
#define LUA_PLUGIN_NAME_VAR_NAME "_MCServerInternal_PluginName"
@@ -11,9 +12,6 @@
-// fwd: Lua
-typedef struct lua_State lua_State;
-
// fwd: UI/Window.h
class cWindow;
@@ -99,7 +97,7 @@ public:
/// Binds the console command to call the function specified by a Lua function reference. Simply adds to CommandMap.
void BindConsoleCommand(const AString & a_Command, int a_FnRef);
- lua_State * GetLuaState(void) { return m_LuaState; }
+ cLuaState & GetLuaState(void) { return m_LuaState; }
cCriticalSection & GetCriticalSection(void) { return m_CriticalSection; }
@@ -114,7 +112,7 @@ public:
protected:
cCriticalSection m_CriticalSection;
- lua_State * m_LuaState;
+ cLuaState m_LuaState;
/// Maps command name into Lua function reference
typedef std::map<AString, int> CommandMap;
@@ -122,9 +120,6 @@ protected:
CommandMap m_Commands;
CommandMap m_ConsoleCommands;
- bool PushFunction(const char * a_FunctionName, bool a_bLogError = true);
- bool CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName ); // a_FunctionName is only used for error messages, nothing else
-
/// Returns the name of Lua function that should handle the specified hook
const char * GetHookFnName(cPluginManager::PluginHook a_Hook);
} ; // tolua_export
diff --git a/source/WebAdmin.cpp b/source/WebAdmin.cpp
index 3d04ce8f3..be7efa18d 100644
--- a/source/WebAdmin.cpp
+++ b/source/WebAdmin.cpp
@@ -178,7 +178,7 @@ void cWebAdmin::Request_Handler(webserver::http_request* r)
if (!bDontShowTemplate)
{
// New Lua web template
- bLuaTemplateSuccessful = WebAdmin->m_pTemplate->CallFunction("ShowPage", sLuaUsertype(WebAdmin, "cWebAdmin"), sLuaUsertype(&TemplateRequest, "HTTPTemplateRequest"), Template);
+ bLuaTemplateSuccessful = WebAdmin->m_pTemplate->CallShowPage(*WebAdmin, TemplateRequest, Template);
}
if (!bLuaTemplateSuccessful)
@@ -274,14 +274,14 @@ bool cWebAdmin::Init( int a_Port )
m_Port = a_Port;
m_IniFile = new cIniFile("webadmin.ini");
- if( m_IniFile->ReadFile() )
+ if (m_IniFile->ReadFile())
{
- m_Port = m_IniFile->GetValueI("WebAdmin", "Port", 8080 );
+ m_Port = m_IniFile->GetValueI("WebAdmin", "Port", 8080);
}
// Initialize the WebAdmin template script and load the file
m_pTemplate->Initialize();
- if (!m_pTemplate->LoadFile( FILE_IO_PREFIX "webadmin/template.lua") || !m_pTemplate->Execute())
+ if (!m_pTemplate->LoadFile(FILE_IO_PREFIX "webadmin/template.lua"))
{
LOGWARN("Could not load WebAdmin template.");
}
diff --git a/source/World.cpp b/source/World.cpp
index 79c0cd4f1..699767d5e 100644
--- a/source/World.cpp
+++ b/source/World.cpp
@@ -58,6 +58,9 @@
#include "tolua++.h"
+// DEBUG: Test out the cLineBlockTracer class by tracing a few lines:
+#include "LineBlockTracer.h"
+
#ifndef _WIN32
#include <stdlib.h>
#endif
@@ -441,6 +444,60 @@ void cWorld::InitializeSpawn(void)
// TODO: Better spawn detection - move spawn out of the water if it isn't set in the INI already
m_SpawnY = (double)GetHeight((int)m_SpawnX, (int)m_SpawnZ) + 1.6f; // +1.6f eye height
+
+
+ #ifdef TEST_LINEBLOCKTRACER
+ // DEBUG: Test out the cLineBlockTracer class by tracing a few lines:
+ class cTracerCallbacks :
+ public cBlockTracer::cCallbacks
+ {
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
+ {
+ LOGD("Block {%d, %d, %d}: %d:%d (%s)",
+ a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta,
+ ItemToString(cItem(a_BlockType, 1, a_BlockMeta)).c_str()
+ );
+ return false;
+ }
+
+ virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ LOGD("Block {%d, %d, %d}: no data available",
+ a_BlockX, a_BlockY, a_BlockZ
+ );
+ return false;
+ }
+
+ virtual bool OnOutOfWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
+ {
+ LOGD("Out of world at {%f, %f, %f}", a_BlockX, a_BlockY, a_BlockZ);
+ return false;
+ }
+
+ virtual bool OnIntoWorld(double a_BlockX, double a_BlockY, double a_BlockZ) override
+ {
+ LOGD("Into world at {%f, %f, %f}", a_BlockX, a_BlockY, a_BlockZ);
+ return false;
+ }
+
+ virtual void OnNoMoreHits(void) override
+ {
+ LOGD("No more hits");
+ }
+ } Callbacks;
+ LOGD("Spawn is at {%f, %f, %f}", m_SpawnX, m_SpawnY, m_SpawnZ);
+ LOGD("Tracing a line along +X:");
+ cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX - 10, m_SpawnY, m_SpawnZ, m_SpawnX + 10, m_SpawnY, m_SpawnZ);
+ LOGD("Tracing a line along -Z:");
+ cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX, m_SpawnY, m_SpawnZ + 10, m_SpawnX, m_SpawnY, m_SpawnZ - 10);
+ LOGD("Tracing a line along -Y, out of world:");
+ cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX, 260, m_SpawnZ, m_SpawnX, -5, m_SpawnZ);
+ LOGD("Tracing a line along XY:");
+ cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX - 10, m_SpawnY - 10, m_SpawnZ, m_SpawnX + 10, m_SpawnY + 10, m_SpawnZ);
+ LOGD("Tracing a line in generic direction:");
+ cLineBlockTracer::Trace(*this, Callbacks, m_SpawnX - 15, m_SpawnY - 5, m_SpawnZ + 7.5, m_SpawnX + 13, m_SpawnY - 10, m_SpawnZ + 8.5);
+ LOGD("Tracing tests done");
+ #endif // TEST_LINEBLOCKTRACER
}
@@ -831,6 +888,15 @@ bool cWorld::GetSignLines(int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_
+bool cWorld::DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback)
+{
+ return m_ChunkMap->DoWithChunk(a_ChunkX, a_ChunkZ, a_Callback);
+}
+
+
+
+
+
void cWorld::GrowTree(int a_X, int a_Y, int a_Z)
{
if (GetBlock(a_X, a_Y, a_Z) == E_BLOCK_SAPLING)
diff --git a/source/World.h b/source/World.h
index 5720ae634..712064af6 100644
--- a/source/World.h
+++ b/source/World.h
@@ -404,6 +404,9 @@ public:
/// a_Player is using block entity at [x, y, z], handle that:
void UseBlockEntity(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) {m_ChunkMap->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); }
+
+ /// Calls the callback for the chunk specified, with ChunkMapCS locked; returns false if the chunk doesn't exist, otherwise returns the same value as the callback
+ bool DoWithChunk(int a_ChunkX, int a_ChunkZ, cChunkCallback & a_Callback);
void GrowTree (int a_BlockX, int a_BlockY, int a_BlockZ); // tolua_export
void GrowTreeFromSapling(int a_BlockX, int a_BlockY, int a_BlockZ, char a_SaplingMeta); // tolua_export