summaryrefslogtreecommitdiffstats
path: root/src/Bindings
diff options
context:
space:
mode:
authorMattes D <github@xoft.cz>2017-06-24 11:58:06 +0200
committerGitHub <noreply@github.com>2017-06-24 11:58:06 +0200
commitfe4253834919d6c742c59c701d3d5ce8285f4504 (patch)
treec201ca7a02344029679d4addffb695a3d20c4bec /src/Bindings
parentLoad entities from old and new names (diff)
downloadcuberite-fe4253834919d6c742c59c701d3d5ce8285f4504.tar
cuberite-fe4253834919d6c742c59c701d3d5ce8285f4504.tar.gz
cuberite-fe4253834919d6c742c59c701d3d5ce8285f4504.tar.bz2
cuberite-fe4253834919d6c742c59c701d3d5ce8285f4504.tar.lz
cuberite-fe4253834919d6c742c59c701d3d5ce8285f4504.tar.xz
cuberite-fe4253834919d6c742c59c701d3d5ce8285f4504.tar.zst
cuberite-fe4253834919d6c742c59c701d3d5ce8285f4504.zip
Diffstat (limited to 'src/Bindings')
-rw-r--r--src/Bindings/CMakeLists.txt1
-rw-r--r--src/Bindings/LuaState.cpp24
-rw-r--r--src/Bindings/LuaState.h4
-rw-r--r--src/Bindings/ManualBindings.cpp373
-rw-r--r--src/Bindings/ManualBindings.h96
-rw-r--r--src/Bindings/ManualBindings_BlockArea.cpp998
6 files changed, 1158 insertions, 338 deletions
diff --git a/src/Bindings/CMakeLists.txt b/src/Bindings/CMakeLists.txt
index 2614ef9b2..747f22157 100644
--- a/src/Bindings/CMakeLists.txt
+++ b/src/Bindings/CMakeLists.txt
@@ -16,6 +16,7 @@ SET (SRCS
LuaUDPEndpoint.cpp
LuaWindow.cpp
ManualBindings.cpp
+ ManualBindings_BlockArea.cpp
ManualBindings_Network.cpp
ManualBindings_RankManager.cpp
ManualBindings_World.cpp
diff --git a/src/Bindings/LuaState.cpp b/src/Bindings/LuaState.cpp
index 947e337fc..d18b6efcd 100644
--- a/src/Bindings/LuaState.cpp
+++ b/src/Bindings/LuaState.cpp
@@ -1762,6 +1762,30 @@ bool cLuaState::CheckParamEnd(int a_Param)
+bool cLuaState::CheckParamSelf(const char * a_SelfClassName)
+{
+ tolua_Error tolua_err;
+ if (tolua_isusertype(m_LuaState, 1, a_SelfClassName, 0, &tolua_err) && !lua_isnil(m_LuaState, 1))
+ {
+ 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(
+ "Error in function '%s'. The 'self' parameter is not of the expected type, \"instance of %s\". Make sure you're using the correct calling convention (obj:fn() instead of obj.fn()).",
+ (entry.name != nullptr) ? entry.name : "<unknown>", a_SelfClassName
+ );
+ tolua_error(m_LuaState, ErrMsg.c_str(), &tolua_err);
+ return false;
+}
+
+
+
+
+
bool cLuaState::IsParamUserType(int a_Param, AString a_UserType)
{
ASSERT(IsValid());
diff --git a/src/Bindings/LuaState.h b/src/Bindings/LuaState.h
index 4320ce40e..674c7a240 100644
--- a/src/Bindings/LuaState.h
+++ b/src/Bindings/LuaState.h
@@ -788,6 +788,10 @@ public:
/** Returns true if the specified parameter on the stack is nil (indicating an end-of-parameters) */
bool CheckParamEnd(int a_Param);
+ /** Returns true if the first parameter is an instance of the expected class name.
+ Returns false and logs a special warning ("wrong calling convention") if not. */
+ bool CheckParamSelf(const char * a_SelfClassName);
+
bool IsParamUserType(int a_Param, AString a_UserType);
bool IsParamNumber(int a_Param);
diff --git a/src/Bindings/ManualBindings.cpp b/src/Bindings/ManualBindings.cpp
index d8bd8b023..2c2de6296 100644
--- a/src/Bindings/ManualBindings.cpp
+++ b/src/Bindings/ManualBindings.cpp
@@ -31,7 +31,6 @@
#include "../BlockEntities/FlowerPotEntity.h"
#include "../Generating/ChunkDesc.h"
#include "../LineBlockTracer.h"
-#include "../WorldStorage/SchematicFileSerializer.h"
#include "../CompositeChat.h"
#include "../StringCompression.h"
#include "../CommandOutput.h"
@@ -133,6 +132,46 @@ int cManualBindings::lua_do_error(lua_State * L, const char * a_pFormat, ...)
+int cManualBindings::ApiParamError(lua_State * a_LuaState, const char * a_MsgFormat, ...)
+{
+ // Retrieve current function name
+ lua_Debug entry;
+ VERIFY(lua_getstack(a_LuaState, 0, &entry));
+ VERIFY(lua_getinfo(a_LuaState, "n", &entry));
+
+ // Compose the error message:
+ va_list argp;
+ va_start(argp, a_MsgFormat);
+ AString msg;
+
+ #ifdef __clang__
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wformat-nonliteral"
+ #endif
+
+ AppendVPrintf(msg, a_MsgFormat, argp);
+
+ #ifdef __clang__
+ #pragma clang diagnostic pop
+ #endif
+
+ va_end(argp);
+ AString errorMsg = Printf("%s: %s", (entry.name != nullptr) ? entry.name : "<unknown function>", msg.c_str());
+
+ // Log everything into the console:
+ LOGWARNING("%s", errorMsg.c_str());
+ // cLuaState::LogStackTrace(a_LuaState); // Do NOT log stack trace, it is already output as part of the Lua error handling
+ cLuaState::LogStackValues(a_LuaState, "Parameters on the stack");
+
+ // Raise Lua error:
+ lua_pushstring(a_LuaState, errorMsg.c_str());
+ return lua_error(a_LuaState);
+}
+
+
+
+
+
// Lua bound functions with special return types
static int tolua_Clamp(lua_State * tolua_S)
{
@@ -3199,324 +3238,6 @@ static int tolua_cHopperEntity_GetOutputBlockPos(lua_State * tolua_S)
-static int tolua_cBlockArea_GetBlockTypeMeta(lua_State * tolua_S)
-{
- // function cBlockArea::GetBlockTypeMeta()
- // Exported manually because tolua generates extra input params for the outputs
-
- cLuaState L(tolua_S);
- if (
- !L.CheckParamUserType(1, "cBlockArea") ||
- !L.CheckParamNumber (2, 4)
- )
- {
- return 0;
- }
-
- cBlockArea * self = reinterpret_cast<cBlockArea *>(tolua_tousertype(tolua_S, 1, nullptr));
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetRelBlockTypeMeta'", nullptr);
- return 0;
- }
- int BlockX = static_cast<int>(tolua_tonumber(tolua_S, 2, 0));
- int BlockY = static_cast<int>(tolua_tonumber(tolua_S, 3, 0));
- int BlockZ = static_cast<int>(tolua_tonumber(tolua_S, 4, 0));
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- self->GetBlockTypeMeta(BlockX, BlockY, BlockZ, BlockType, BlockMeta);
- tolua_pushnumber(tolua_S, BlockType);
- tolua_pushnumber(tolua_S, BlockMeta);
- return 2;
-}
-
-
-
-
-
-static int tolua_cBlockArea_GetOrigin(lua_State * tolua_S)
-{
- // function cBlockArea::GetOrigin()
- // Returns all three coords of the origin point
- // Exported manually because there's no direct C++ equivalent,
- // plus tolua would generate extra input params for the outputs
-
- cLuaState L(tolua_S);
- if (!L.CheckParamUserType(1, "cBlockArea"))
- {
- return 0;
- }
-
- cBlockArea * self = reinterpret_cast<cBlockArea *>(tolua_tousertype(tolua_S, 1, nullptr));
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetOrigin'", nullptr);
- return 0;
- }
-
- // Push the three origin coords:
- lua_pushnumber(tolua_S, self->GetOriginX());
- lua_pushnumber(tolua_S, self->GetOriginY());
- lua_pushnumber(tolua_S, self->GetOriginZ());
- return 3;
-}
-
-
-
-
-
-static int tolua_cBlockArea_GetNonAirCropRelCoords(lua_State * tolua_S)
-{
- // function cBlockArea::GetNonAirCropRelCoords()
- // Exported manually because tolua would generate extra input params for the outputs
-
- cLuaState L(tolua_S);
- if (!L.CheckParamUserType(1, "cBlockArea"))
- {
- return 0;
- }
-
- cBlockArea * self = nullptr;
- BLOCKTYPE IgnoreBlockType = E_BLOCK_AIR;
- L.GetStackValues(1, self, IgnoreBlockType);
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetNonAirCropRelCoords'", nullptr);
- return 0;
- }
-
- // Calculate the crop coords:
- int MinRelX, MinRelY, MinRelZ, MaxRelX, MaxRelY, MaxRelZ;
- self->GetNonAirCropRelCoords(MinRelX, MinRelY, MinRelZ, MaxRelX, MaxRelY, MaxRelZ, IgnoreBlockType);
-
- // Push the six crop coords:
- L.Push(MinRelX, MinRelY, MinRelZ, MaxRelX, MaxRelY, MaxRelZ);
- return 6;
-}
-
-
-
-
-
-static int tolua_cBlockArea_GetRelBlockTypeMeta(lua_State * tolua_S)
-{
- // function cBlockArea::GetRelBlockTypeMeta()
- // Exported manually because tolua generates extra input params for the outputs
-
- cLuaState L(tolua_S);
- if (
- !L.CheckParamUserType(1, "cBlockArea") ||
- !L.CheckParamNumber (2, 4)
- )
- {
- return 0;
- }
-
- cBlockArea * self = reinterpret_cast<cBlockArea *>(tolua_tousertype(tolua_S, 1, nullptr));
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetRelBlockTypeMeta'", nullptr);
- return 0;
- }
- int BlockX = static_cast<int>(tolua_tonumber(tolua_S, 2, 0));
- int BlockY = static_cast<int>(tolua_tonumber(tolua_S, 3, 0));
- int BlockZ = static_cast<int>(tolua_tonumber(tolua_S, 4, 0));
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- self->GetRelBlockTypeMeta(BlockX, BlockY, BlockZ, BlockType, BlockMeta);
- tolua_pushnumber(tolua_S, BlockType);
- tolua_pushnumber(tolua_S, BlockMeta);
- return 2;
-}
-
-
-
-
-
-static int tolua_cBlockArea_GetSize(lua_State * tolua_S)
-{
- // function cBlockArea::GetSize()
- // Returns all three sizes of the area
- // Exported manually because there's no direct C++ equivalent,
- // plus tolua would generate extra input params for the outputs
-
- cLuaState L(tolua_S);
- if (!L.CheckParamUserType(1, "cBlockArea"))
- {
- return 0;
- }
-
- cBlockArea * self = reinterpret_cast<cBlockArea *>(tolua_tousertype(tolua_S, 1, nullptr));
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetSize'", nullptr);
- return 0;
- }
-
- // Push the three origin coords:
- lua_pushnumber(tolua_S, self->GetSizeX());
- lua_pushnumber(tolua_S, self->GetSizeY());
- lua_pushnumber(tolua_S, self->GetSizeZ());
- return 3;
-}
-
-
-
-
-
-static int tolua_cBlockArea_GetCoordRange(lua_State * tolua_S)
-{
- // function cBlockArea::GetCoordRange()
- // Returns all three sizes of the area, miuns one, so that they represent the maximum coord value
- // Exported manually because there's no direct C++ equivalent,
- // plus tolua would generate extra input params for the outputs
-
- cLuaState L(tolua_S);
- if (!L.CheckParamUserType(1, "cBlockArea"))
- {
- return 0;
- }
-
- cBlockArea * self = reinterpret_cast<cBlockArea *>(tolua_tousertype(tolua_S, 1, nullptr));
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea:GetSize'", nullptr);
- return 0;
- }
-
- // Push the three origin coords:
- lua_pushnumber(tolua_S, self->GetSizeX() - 1);
- lua_pushnumber(tolua_S, self->GetSizeY() - 1);
- lua_pushnumber(tolua_S, self->GetSizeZ() - 1);
- return 3;
-}
-
-
-
-
-
-static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * tolua_S)
-{
- // function cBlockArea::LoadFromSchematicFile
- // Exported manually because function has been moved to SchematicFileSerializer.cpp
- cLuaState L(tolua_S);
- if (
- !L.CheckParamUserType(1, "cBlockArea") ||
- !L.CheckParamString (2) ||
- !L.CheckParamEnd (3)
- )
- {
- return 0;
- }
- cBlockArea * self = reinterpret_cast<cBlockArea *>(tolua_tousertype(tolua_S, 1, nullptr));
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::LoadFromSchematicFile'", nullptr);
- return 0;
- }
-
- AString Filename = tolua_tostring(tolua_S, 2, 0);
- bool res = cSchematicFileSerializer::LoadFromSchematicFile(*self, Filename);
- tolua_pushboolean(tolua_S, res);
- return 1;
-}
-
-
-
-
-
-static int tolua_cBlockArea_LoadFromSchematicString(lua_State * tolua_S)
-{
- // function cBlockArea::LoadFromSchematicString
- // Exported manually because function has been moved to SchematicFileSerializer.cpp
- cLuaState L(tolua_S);
- if (
- !L.CheckParamUserType(1, "cBlockArea") ||
- !L.CheckParamString (2) ||
- !L.CheckParamEnd (3)
- )
- {
- return 0;
- }
- cBlockArea * self = reinterpret_cast<cBlockArea *>(tolua_tousertype(tolua_S, 1, nullptr));
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::LoadFromSchematicFile'", nullptr);
- return 0;
- }
-
- AString Data;
- L.GetStackValue(2, Data);
- bool res = cSchematicFileSerializer::LoadFromSchematicString(*self, Data);
- tolua_pushboolean(tolua_S, res);
- return 1;
-}
-
-
-
-
-
-static int tolua_cBlockArea_SaveToSchematicFile(lua_State * tolua_S)
-{
- // function cBlockArea::SaveToSchematicFile
- // Exported manually because function has been moved to SchematicFileSerializer.cpp
- cLuaState L(tolua_S);
- if (
- !L.CheckParamUserType(1, "cBlockArea") ||
- !L.CheckParamString (2) ||
- !L.CheckParamEnd (3)
- )
- {
- return 0;
- }
- cBlockArea * self = reinterpret_cast<cBlockArea *>(tolua_tousertype(tolua_S, 1, nullptr));
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::SaveToSchematicFile'", nullptr);
- return 0;
- }
- AString Filename = tolua_tostring(tolua_S, 2, 0);
- bool res = cSchematicFileSerializer::SaveToSchematicFile(*self, Filename);
- tolua_pushboolean(tolua_S, res);
- return 1;
-}
-
-
-
-
-
-static int tolua_cBlockArea_SaveToSchematicString(lua_State * tolua_S)
-{
- // function cBlockArea::SaveToSchematicString
- // Exported manually because function has been moved to SchematicFileSerializer.cpp
- cLuaState L(tolua_S);
- if (
- !L.CheckParamUserType(1, "cBlockArea") ||
- !L.CheckParamEnd (2)
- )
- {
- return 0;
- }
- cBlockArea * self = reinterpret_cast<cBlockArea *>(tolua_tousertype(tolua_S, 1, nullptr));
- if (self == nullptr)
- {
- tolua_error(tolua_S, "invalid 'self' in function 'cBlockArea::SaveToSchematicFile'", nullptr);
- return 0;
- }
-
- AString Data;
- if (cSchematicFileSerializer::SaveToSchematicString(*self, Data))
- {
- L.Push(Data);
- return 1;
- }
- return 0;
-}
-
-
-
-
-
static int tolua_cBoundingBox_CalcLineIntersection(lua_State * a_LuaState)
{
/* Function signatures:
@@ -4031,19 +3752,6 @@ void cManualBindings::Bind(lua_State * tolua_S)
tolua_function(tolua_S, "Base64Decode", tolua_Base64Decode);
tolua_function(tolua_S, "md5", tolua_md5_obsolete); // OBSOLETE, use cCryptoHash.md5() instead
- tolua_beginmodule(tolua_S, "cBlockArea");
- tolua_function(tolua_S, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta);
- tolua_function(tolua_S, "GetCoordRange", tolua_cBlockArea_GetCoordRange);
- tolua_function(tolua_S, "GetOrigin", tolua_cBlockArea_GetOrigin);
- tolua_function(tolua_S, "GetNonAirCropRelCoords", tolua_cBlockArea_GetNonAirCropRelCoords);
- tolua_function(tolua_S, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta);
- tolua_function(tolua_S, "GetSize", tolua_cBlockArea_GetSize);
- tolua_function(tolua_S, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile);
- tolua_function(tolua_S, "LoadFromSchematicString", tolua_cBlockArea_LoadFromSchematicString);
- tolua_function(tolua_S, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile);
- tolua_function(tolua_S, "SaveToSchematicString", tolua_cBlockArea_SaveToSchematicString);
- tolua_endmodule(tolua_S);
-
tolua_beginmodule(tolua_S, "cBoundingBox");
tolua_function(tolua_S, "CalcLineIntersection", tolua_cBoundingBox_CalcLineIntersection);
tolua_function(tolua_S, "Intersect", tolua_cBoundingBox_Intersect);
@@ -4228,6 +3936,7 @@ void cManualBindings::Bind(lua_State * tolua_S)
BindNetwork(tolua_S);
BindRankManager(tolua_S);
BindWorld(tolua_S);
+ BindBlockArea(tolua_S);
tolua_endmodule(tolua_S);
}
diff --git a/src/Bindings/ManualBindings.h b/src/Bindings/ManualBindings.h
index 98e3e88ef..889e33664 100644
--- a/src/Bindings/ManualBindings.h
+++ b/src/Bindings/ManualBindings.h
@@ -41,6 +41,10 @@ protected:
Implemented in ManualBindings_World.cpp. */
static void BindWorld(lua_State * tolua_S);
+ /** Binds the manually implemented cBlockArea API functions to tlua_S.
+ Implemented in ManualBindings_BlockArea.cpp. */
+ static void BindBlockArea(lua_State * tolua_S);
+
public:
// Helper functions:
@@ -48,6 +52,11 @@ public:
static int tolua_do_error(lua_State * L, const char * a_pMsg, tolua_Error * a_pToLuaError);
static int lua_do_error(lua_State * L, const char * a_pFormat, ...);
+ /** Formats and prints the message, prefixed with the current function name, then logs the stack contents and raises a Lua error.
+ To be used for bindings when they detect bad parameters.
+ Doesn't return, but a dummy return type is provided so that Lua API functions may do "return ApiParamError(...)". */
+ static int ApiParamError(lua_State * a_LuaState, const char * a_MsgFormat, ...);
+
/** Binds the DoWith(ItemName) functions of regular classes. */
template <
@@ -243,10 +252,11 @@ public:
+ /** Template for the bindings for the DoWithXYZAt(X, Y, Z) functions that don't need to check their coords. */
template <
- class Ty1,
- class Ty2,
- bool (Ty1::*DoWithFn)(int, int, int, cItemCallback<Ty2> &)
+ class SELF,
+ class ITEM,
+ bool (SELF::*DoWithFn)(int, int, int, cItemCallback<ITEM> &)
>
static int DoWithXYZ(lua_State * tolua_S)
{
@@ -262,7 +272,7 @@ public:
}
// Get parameters:
- Ty1 * Self = nullptr;
+ SELF * Self = nullptr;
int BlockX = 0;
int BlockY = 0;
int BlockZ = 0;
@@ -277,7 +287,7 @@ public:
return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #5");
}
- class cLuaCallback : public cItemCallback<Ty2>
+ class cLuaCallback : public cItemCallback<ITEM>
{
public:
cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
@@ -287,7 +297,81 @@ public:
}
private:
- virtual bool Item(Ty2 * a_Item) override
+ virtual bool Item(ITEM * a_Item) override
+ {
+ bool ret = false;
+ m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
+ return ret;
+ }
+ cLuaState & m_LuaState;
+ cLuaState::cRef & m_FnRef;
+ } Callback(L, FnRef);
+
+ // Call the DoWith function:
+ bool res = (Self->*DoWithFn)(BlockX, BlockY, BlockZ, Callback);
+
+ // Push the result as the return value:
+ L.Push(res);
+ return 1;
+ }
+
+
+
+
+
+ /** Template for the bindings for the DoWithXYZAt(X, Y, Z) functions that need to check their coords. */
+ template <
+ class SELF,
+ class ITEM,
+ bool (SELF::*DoWithFn)(int, int, int, cItemCallback<ITEM> &),
+ bool (SELF::*CoordCheckFn)(int, int, int) const
+ >
+ static int DoWithXYZ(lua_State * tolua_S)
+ {
+ // Check params:
+ cLuaState L(tolua_S);
+ if (
+ !L.CheckParamNumber(2, 4) ||
+ !L.CheckParamFunction(5) ||
+ !L.CheckParamEnd(6)
+ )
+ {
+ return 0;
+ }
+
+ // Get parameters:
+ SELF * Self = nullptr;
+ int BlockX = 0;
+ int BlockY = 0;
+ int BlockZ = 0;
+ cLuaState::cRef FnRef;
+ L.GetStackValues(1, Self, BlockX, BlockY, BlockZ, FnRef);
+ if (Self == nullptr)
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Invalid 'self'");
+ }
+ if (!FnRef.IsValid())
+ {
+ return lua_do_error(tolua_S, "Error in function call '#funcname#': Expected a valid callback function for parameter #5");
+ }
+ if (!(Self->*CoordCheckFn)(BlockX, BlockY, BlockZ))
+ {
+ return lua_do_error(tolua_S, Printf("Error in function call '#funcname#': The provided coordinates ({%d, %d, %d}) are not valid",
+ BlockX, BlockY, BlockZ
+ ).c_str());
+ }
+
+ class cLuaCallback : public cItemCallback<ITEM>
+ {
+ public:
+ cLuaCallback(cLuaState & a_LuaState, cLuaState::cRef & a_FnRef):
+ m_LuaState(a_LuaState),
+ m_FnRef(a_FnRef)
+ {
+ }
+
+ private:
+ virtual bool Item(ITEM * a_Item) override
{
bool ret = false;
m_LuaState.Call(m_FnRef, a_Item, cLuaState::Return, ret);
diff --git a/src/Bindings/ManualBindings_BlockArea.cpp b/src/Bindings/ManualBindings_BlockArea.cpp
new file mode 100644
index 000000000..14462c6e9
--- /dev/null
+++ b/src/Bindings/ManualBindings_BlockArea.cpp
@@ -0,0 +1,998 @@
+// ManualBindings_BlockArea.cpp
+
+// Implements the manual bindings for functions in the cBlockArea class
+
+#include "Globals.h"
+#include "tolua++/include/tolua++.h"
+#include "../BlockArea.h"
+#include "../World.h"
+#include "ManualBindings.h"
+#include "LuaState.h"
+#include "PluginLua.h"
+#include "../WorldStorage/SchematicFileSerializer.h"
+
+
+
+
+
+
+/** Reads params that together form a Cuboid.
+These can be:
+ - 6 numbers (MinX, MaxX, MinY, MaxY, MinZ, MaxZ)
+ - 2 Vector3-s (Min, Max)
+ - cCuboid
+Returns the index of the first parameter following the Cuboid spec.
+Raises an Api error if the params don't specify a Cuboid.
+*/
+static int readCuboidOverloadParams(cLuaState & a_LuaState, int a_StartParam, cCuboid & a_Cuboid)
+{
+ if (a_LuaState.IsParamNumber(a_StartParam))
+ {
+ // Assume the 6-number version:
+ if (!a_LuaState.GetStackValues(a_StartParam, a_Cuboid.p1.x, a_Cuboid.p2.x, a_Cuboid.p1.y, a_Cuboid.p2.y, a_Cuboid.p1.z, a_Cuboid.p2.z))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the bounds parameters, expected 6 numbers.");
+ }
+ return a_StartParam + 6;
+ }
+ else if (a_LuaState.IsParamUserType(a_StartParam, "cCuboid"))
+ {
+ // Assume the cCuboid version:
+ cCuboid * c;
+ if (!a_LuaState.GetStackValues(a_StartParam, c))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the bounds parameter, expected a cCuboid instance.");
+ }
+ a_Cuboid = *c;
+ return a_StartParam + 1;
+ }
+ else
+ {
+ // Assume the 2-Vector3i version:
+ Vector3i * p1;
+ Vector3i * p2;
+ if (!a_LuaState.GetStackValues(a_StartParam, p1, p2))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the bounds parameter, expected two Vector3i instances.");
+ }
+ a_Cuboid.p1 = *p1;
+ a_Cuboid.p2 = *p2;
+ return a_StartParam + 2;
+ }
+}
+
+
+
+
+
+/** Reads params that together form a Vector3i.
+These can be:
+ - 3 numbers (x, y, z)
+ - Vector3i
+Returns the index of the first parameter following the Vector3i spec.
+Raises an Api error if the params don't specify a Vector3i.
+*/
+static int readVector3iOverloadParams(cLuaState & a_LuaState, int a_StartParam, Vector3i & a_Coords, const char * a_ParamName)
+{
+ if (a_LuaState.IsParamNumber(a_StartParam))
+ {
+ // Assume the 3-number version:
+ if (!a_LuaState.GetStackValues(a_StartParam, a_Coords.x, a_Coords.y, a_Coords.z))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the %s, expected 3 numbers.", a_ParamName);
+ }
+ return a_StartParam + 3;
+ }
+ else
+ {
+ // Assume the Vector3i version:
+ Vector3i * c;
+ if (!a_LuaState.GetStackValues(a_StartParam, c))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the %s, expected a Vector3i instance.", a_ParamName);
+ }
+ a_Coords = *c;
+ return a_StartParam + 1;
+ }
+}
+
+
+
+
+
+/** Binding for the cBlockArea::Create() functions. Supports two overloads and one default parameter. */
+static int tolua_cBlockArea_Create(lua_State * a_LuaState)
+{
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+ cBlockArea * self = nullptr;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read self.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ int dataTypes = cBlockArea::baTypes | cBlockArea::baMetas | cBlockArea::baBlockEntities;
+ Vector3i size;
+ auto dataTypesIdx = readVector3iOverloadParams(L, 2, size, "size");
+ L.GetStackValue(dataTypesIdx, dataTypes);
+ if (!cBlockArea::IsValidDataTypeCombination(dataTypes))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid combination of baDataTypes specified (%d).", dataTypes);
+ }
+
+ // Create the area:
+ if ((size.x <= 0) || (size.y <= 0) || (size.z <= 0))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid sizes, must be greater than zero, got {%d, %d, %d}", size.x, size.y, size.z);
+ }
+ ASSERT(self != nullptr);
+ self->Create(size, dataTypes);
+ return 0;
+}
+
+
+
+
+
+/** Bindings for the cBlockArea:FillRelCuboid() functions. Supports coord overloads and one default parameter. */
+static int tolua_cBlockArea_FillRelCuboid(lua_State * a_LuaState)
+{
+ // Check the common params:
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ // Get the common params:
+ cBlockArea * self = nullptr;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read self.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ // Check and get the overloaded params:
+ cCuboid bounds;
+ auto nextIdx = readCuboidOverloadParams(L, 2, bounds);
+ int dataTypes = cBlockArea::baTypes | cBlockArea::baMetas | cBlockArea::baBlockEntities;
+ BLOCKTYPE blockType;
+ NIBBLETYPE blockMeta = 0, blockLight = 0, blockSkyLight = 0x0f;
+ if (!L.GetStackValues(nextIdx, dataTypes, blockType))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the datatypes or block type params");
+ }
+ L.GetStackValues(nextIdx + 2, blockMeta, blockLight, blockSkyLight); // These values are optional
+ if (!cBlockArea::IsValidDataTypeCombination(dataTypes))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid baDataTypes combination (%d).", dataTypes);
+ }
+
+ // Check the coords, shift if needed:
+ bounds.Sort();
+ bounds.ClampX(0, self->GetSizeX());
+ bounds.ClampY(0, self->GetSizeY());
+ bounds.ClampZ(0, self->GetSizeZ());
+
+ // Do the actual Fill:
+ self->FillRelCuboid(bounds, dataTypes, blockType, blockMeta, blockLight, blockSkyLight);
+ return 0;
+}
+
+
+
+
+
+static int tolua_cBlockArea_GetBlockTypeMeta(lua_State * a_LuaState)
+{
+ // function cBlockArea::GetBlockTypeMeta()
+
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read 'self'");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ Vector3i coords;
+ readVector3iOverloadParams(L, 2, coords, "coords");
+ if (!self->IsValidCoords(coords))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Coords ({%d, %d, %d}) out of range ({%d, %d, %d} - {%d, %d, %d}).",
+ coords.x, coords.y, coords.z,
+ self->GetOriginX(), self->GetOriginY(), self->GetOriginZ(),
+ self->GetOriginX() + self->GetSizeX() - 1, self->GetOriginY() + self->GetSizeY() - 1, self->GetOriginZ() + self->GetSizeZ() - 1
+ );
+ }
+ BLOCKTYPE blockType;
+ NIBBLETYPE blockMeta;
+ self->GetBlockTypeMeta(coords.x, coords.y, coords.z, blockType, blockMeta);
+ L.Push(blockType, blockMeta);
+ return 2;
+}
+
+
+
+
+
+static int tolua_cBlockArea_GetCoordRange(lua_State * a_LuaState)
+{
+ // function cBlockArea::GetCoordRange()
+ // Returns all three sizes of the area, each minus one, so that they represent the maximum coord value
+ // Exported manually because there's no direct C++ equivalent,
+ // plus tolua would generate extra input params for the outputs
+
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the 'self' parameter.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ L.Push(self->GetSizeX() - 1, self->GetSizeY() - 1, self->GetSizeZ() - 1);
+ return 3;
+}
+
+
+
+
+
+static int tolua_cBlockArea_GetNonAirCropRelCoords(lua_State * a_LuaState)
+{
+ // function cBlockArea::GetNonAirCropRelCoords()
+ // Exported manually because tolua would generate extra input params for the outputs
+
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ cBlockArea * self = nullptr;
+ BLOCKTYPE ignoreBlockType = E_BLOCK_AIR;
+ if (!L.GetStackValues(1, self, ignoreBlockType))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read params");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil");
+ }
+ if (!self->HasBlockTypes())
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The area doesn't contain baTypes datatype");
+ }
+
+ // Calculate the crop coords:
+ int minRelX, minRelY, minRelZ, maxRelX, maxRelY, maxRelZ;
+ self->GetNonAirCropRelCoords(minRelX, minRelY, minRelZ, maxRelX, maxRelY, maxRelZ, ignoreBlockType);
+
+ // Push the six crop coords:
+ L.Push(minRelX, minRelY, minRelZ, maxRelX, maxRelY, maxRelZ);
+ return 6;
+}
+
+
+
+
+
+static int tolua_cBlockArea_GetOrigin(lua_State * a_LuaState)
+{
+ // function cBlockArea::GetOrigin()
+ // Returns all three coords of the origin point
+ // Exported manually because there's no direct C++ equivalent,
+ // plus tolua would generate extra input params for the outputs
+
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the 'self' parameter.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ // Push the three origin coords:
+ L.Push(self->GetOriginX(), self->GetOriginY(), self->GetOriginZ());
+ return 3;
+}
+
+
+
+
+
+static int tolua_cBlockArea_GetRelBlockTypeMeta(lua_State * a_LuaState)
+{
+ // function cBlockArea::GetRelBlockTypeMeta()
+ // Exported manually because tolua generates extra input params for the outputs
+
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the 'self' parameter.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+ if (!self->HasBlockTypes())
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The area doesn't contain baTypes datatype");
+ }
+ if (!self->HasBlockMetas())
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The area doesn't contain baMetas datatype");
+ }
+
+ Vector3i coords;
+ readVector3iOverloadParams(L, 2, coords, "coords");
+ if (!self->IsValidRelCoords(coords))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The coords ({%d, %d, %d}) are out of range (max {%d, %d, %d}).",
+ coords.x, coords.y, coords.z,
+ self->GetSizeX() - 1, self->GetSizeY() - 1, self->GetSizeZ() - 1
+ );
+ }
+ BLOCKTYPE blockType;
+ NIBBLETYPE blockMeta;
+ self->GetRelBlockTypeMeta(coords.x, coords.y, coords.z, blockType, blockMeta);
+ L.Push(blockType, blockMeta);
+ return 2;
+}
+
+
+
+
+
+static int tolua_cBlockArea_GetSize(lua_State * a_LuaState)
+{
+ // function cBlockArea::GetSize()
+ // Returns all three sizes of the area
+ // Exported manually because there's no direct C++ equivalent,
+ // plus tolua would generate extra input params for the outputs
+
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the 'self' parameter.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ L.Push(self->GetSizeX(), self->GetSizeY(), self->GetSizeZ());
+ return 3;
+}
+
+
+
+
+
+static int tolua_cBlockArea_LoadFromSchematicFile(lua_State * a_LuaState)
+{
+ // function cBlockArea::LoadFromSchematicFile
+ // Exported manually because function has been moved to SchematicFileSerializer.cpp
+ cLuaState L(a_LuaState);
+ if (
+ !L.CheckParamSelf("cBlockArea") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+ cBlockArea * self;
+ AString fileName;
+ if (!L.GetStackValues(1, self, fileName))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the parameters.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ L.Push(cSchematicFileSerializer::LoadFromSchematicFile(*self, fileName));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cBlockArea_LoadFromSchematicString(lua_State * a_LuaState)
+{
+ // function cBlockArea::LoadFromSchematicString
+ // Exported manually because function has been moved to SchematicFileSerializer.cpp
+ cLuaState L(a_LuaState);
+ if (
+ !L.CheckParamSelf("cBlockArea") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+ cBlockArea * self;
+ AString data;
+ if (!L.GetStackValues(1, self, data))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the parameters.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ L.Push(cSchematicFileSerializer::LoadFromSchematicString(*self, data));
+ return 1;
+}
+
+
+
+
+
+/** Bindings for the cBlockArea:Read() functions. Supports three overloads and one default parameter. */
+static int tolua_cBlockArea_Read(lua_State * a_LuaState)
+{
+ // Check the common params:
+ cLuaState L(a_LuaState);
+ if (
+ !L.CheckParamSelf("cBlockArea") ||
+ !L.CheckParamUserType(2, "cWorld")
+ )
+ {
+ return 0;
+ }
+
+ // Get the common params:
+ cBlockArea * self = nullptr;
+ cWorld * world = nullptr;
+ if (!L.GetStackValues(1, self, world))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read self or world.");
+ }
+ if (world == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid world instance. The world must be not nil.");
+ }
+
+ // Check and get the overloaded params:
+ cCuboid bounds;
+ int dataTypes = cBlockArea::baTypes | cBlockArea::baMetas | cBlockArea::baBlockEntities;
+ auto dataTypesIdx = readCuboidOverloadParams(L, 3, bounds);
+ L.GetStackValues(dataTypesIdx, dataTypes);
+ if (!cBlockArea::IsValidDataTypeCombination(dataTypes))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid baDataTypes combination (%d).", dataTypes);
+ }
+
+ // Check the coords, shift if needed:
+ bounds.Sort();
+ if (bounds.p1.y < 0)
+ {
+ LOGWARNING("cBlockArea:Read(): MinBlockY less than zero, adjusting to zero. Coords: {%d, %d, %d} - {%d, %d, %d}",
+ bounds.p1.x, bounds.p1.y, bounds.p1.z, bounds.p2.x, bounds.p2.y, bounds.p2.z
+ );
+ L.LogStackTrace();
+ bounds.p1.y = 0;
+ }
+ else if (bounds.p1.y >= cChunkDef::Height)
+ {
+ LOGWARNING("cBlockArea:Read(): MinBlockY more than chunk height, adjusting to chunk height. Coords: {%d, %d, %d} - {%d, %d, %d}",
+ bounds.p1.x, bounds.p1.y, bounds.p1.z, bounds.p2.x, bounds.p2.y, bounds.p2.z
+ );
+ L.LogStackTrace();
+ bounds.p1.y = cChunkDef::Height - 1;
+ }
+ if (bounds.p2.y < 0)
+ {
+ LOGWARNING("cBlockArea:Read(): MaxBlockY less than zero, adjusting to zero. Coords: {%d, %d, %d} - {%d, %d, %d}",
+ bounds.p1.x, bounds.p1.y, bounds.p1.z, bounds.p2.x, bounds.p2.y, bounds.p2.z
+ );
+ L.LogStackTrace();
+ bounds.p2.y = 0;
+ }
+ else if (bounds.p2.y > cChunkDef::Height)
+ {
+ LOGWARNING("cBlockArea:Read(): MaxBlockY more than chunk height, adjusting to chunk height. Coords: {%d, %d, %d} - {%d, %d, %d}",
+ bounds.p1.x, bounds.p1.y, bounds.p1.z, bounds.p2.x, bounds.p2.y, bounds.p2.z
+ );
+ L.LogStackTrace();
+ bounds.p2.y = cChunkDef::Height;
+ }
+
+ // Do the actual read:
+ L.Push(self->Read(*world, bounds, dataTypes));
+ return 1;
+}
+
+
+
+
+
+/** Bindings for the cBlockArea:RelLine() functions. Supports two overloads and one default parameter.
+Also supports "bastard overloads" (Vector3i, x, y, z), but we don't advertise those. */
+static int tolua_cBlockArea_RelLine(lua_State * a_LuaState)
+{
+ // Check the common params:
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ // Get the common params:
+ cBlockArea * self = nullptr;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read self.");
+ }
+
+ // Check and get the overloaded params:
+ Vector3i p1;
+ auto idx = readVector3iOverloadParams(L, 2, p1, "start coords");
+ Vector3i p2;
+ idx = readVector3iOverloadParams(L, idx, p2, "end coords");
+ int dataTypes = cBlockArea::baTypes | cBlockArea::baMetas | cBlockArea::baBlockEntities;
+ BLOCKTYPE blockType;
+ NIBBLETYPE blockMeta, blockLight, blockSkyLight;
+ L.GetStackValues(idx, dataTypes, blockType, blockMeta, blockLight, blockSkyLight);
+ if (!cBlockArea::IsValidDataTypeCombination(dataTypes))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid baDataTypes combination (%d).", dataTypes);
+ }
+
+ // Draw the line:
+ self->RelLine(p1, p2, dataTypes, blockType, blockMeta, blockLight, blockSkyLight);
+ return 0;
+}
+
+
+
+
+
+static int tolua_cBlockArea_SaveToSchematicFile(lua_State * a_LuaState)
+{
+ // function cBlockArea::SaveToSchematicFile
+ // Exported manually because function has been moved to SchematicFileSerializer.cpp
+ cLuaState L(a_LuaState);
+ if (
+ !L.CheckParamSelf("cBlockArea") ||
+ !L.CheckParamString(2) ||
+ !L.CheckParamEnd(3)
+ )
+ {
+ return 0;
+ }
+ cBlockArea * self;
+ AString fileName;
+ if (!L.GetStackValues(1, self, fileName))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the parameters.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ L.Push(cSchematicFileSerializer::SaveToSchematicFile(*self, fileName));
+ return 1;
+}
+
+
+
+
+
+static int tolua_cBlockArea_SaveToSchematicString(lua_State * a_LuaState)
+{
+ // function cBlockArea::SaveToSchematicString
+ // Exported manually because function has been moved to SchematicFileSerializer.cpp
+ cLuaState L(a_LuaState);
+ if (
+ !L.CheckParamSelf("cBlockArea") ||
+ !L.CheckParamEnd(2)
+ )
+ {
+ return 0;
+ }
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the 'self' parameter.");
+ }
+ if (self == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid 'self', must not be nil.");
+ }
+
+ AString data;
+ if (cSchematicFileSerializer::SaveToSchematicString(*self, data))
+ {
+ L.Push(data);
+ return 1;
+ }
+ return 0;
+}
+
+
+
+
+
+/** Bindings for the cBlockArea:Write() functions. Supports two overloads and one default parameter. */
+static int tolua_cBlockArea_Write(lua_State * a_LuaState)
+{
+ // Check the common params:
+ cLuaState L(a_LuaState);
+ if (
+ !L.CheckParamSelf("cBlockArea") ||
+ !L.CheckParamUserType(2, "cWorld")
+ )
+ {
+ return 0;
+ }
+
+ // Get the common params:
+ cBlockArea * self = nullptr;
+ cWorld * world = nullptr;
+ if (!L.GetStackValues(1, self, world))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read self or world.");
+ }
+ if (world == nullptr)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid world instance. The world must be not nil.");
+ }
+
+ // Check and get the overloaded params:
+ Vector3i coords;
+ int dataTypes = cBlockArea::baTypes | cBlockArea::baMetas | cBlockArea::baBlockEntities;
+ auto dataTypesIdx = readVector3iOverloadParams(L, 3, coords, "coords");
+ L.GetStackValues(dataTypesIdx, dataTypes);
+
+ // Check the dataType parameter validity:
+ if (!cBlockArea::IsValidDataTypeCombination(dataTypes))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Invalid datatype combination (%d).", dataTypes);
+ }
+ if ((self->GetDataTypes() & dataTypes) != dataTypes)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Requesting datatypes not present in the cBlockArea. Got only 0x%02x, requested 0x%02x",
+ self->GetDataTypes(), dataTypes
+ );
+ }
+
+ // Check and adjust the coord params:
+ // TODO: Should we report this as a failure? Because the result is definitely not what the plugin assumed
+ // ... Or should we silently clone-crop-write the cBlockArea so that the API call does what would be naturally expected?
+ // ... Or should we change the cBlockArea::Write() to allow out-of-range Y coords and do the cropping there?
+ // ... NOTE: We already support auto-crop in cBlockArea::Merge() itself
+ if (coords.y < 0)
+ {
+ LOGWARNING("cBlockArea:Write(): MinBlockY less than zero, adjusting to zero");
+ L.LogStackTrace();
+ coords.y = 0;
+ }
+ else if (coords.y > cChunkDef::Height - self->GetSizeY())
+ {
+ LOGWARNING("cBlockArea:Write(): MinBlockY + m_SizeY more than chunk height, adjusting to chunk height");
+ L.LogStackTrace();
+ coords.y = cChunkDef::Height - self->GetSizeY();
+ }
+
+ // Do the actual write:
+ L.Push(self->Write(*world, coords, dataTypes));
+ return 1;
+}
+
+
+
+
+
+/** Templated bindings for the GetBlock___() functions.
+DataType is either BLOCKTYPE or NIBBLETYPE.
+DataTypeFlag is the ba___ constant used for the datatype being queried.
+Fn is the getter function.
+Also supports the Vector3i overloads (TODO: document these (?)). */
+template <
+ typename DataType,
+ int DataTypeFlag,
+ DataType (cBlockArea::*Fn)(int, int, int) const
+>
+static int GetBlock(lua_State * a_LuaState)
+{
+ // Check the common params:
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ // Read the common params:
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the 'self' param.");
+ }
+
+ // Check the datatype's presence:
+ if ((self->GetDataTypes() & DataTypeFlag) == 0)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The area doesn't contain the datatype (%d).", DataTypeFlag);
+ }
+
+ // Read the overloaded params:
+ Vector3i coords;
+ readVector3iOverloadParams(L, 2, coords, "coords");
+ if (!self->IsValidCoords(coords))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The coords ({%d, %d, %d}) are out of range ({%d, %d, %d} - {%d, %d, %d}).",
+ coords.x, coords.y, coords.z,
+ self->GetOriginX(), self->GetOriginY(), self->GetOriginZ(),
+ self->GetOriginX() + self->GetSizeX() - 1, self->GetOriginY() + self->GetSizeY() - 1, self->GetOriginZ() + self->GetSizeZ() - 1
+ );
+ }
+
+ // Get the block info:
+ L.Push((self->*Fn)(coords.x, coords.y, coords.z));
+ return 1;
+}
+
+
+
+
+
+/** Templated bindings for the GetRelBlock___() functions.
+DataType is either BLOCKTYPE or NIBBLETYPE.
+DataTypeFlag is the ba___ constant used for the datatype being queried.
+Fn is the getter function.
+Also supports the Vector3i overloads (TODO: document these (?)). */
+template <
+ typename DataType,
+ int DataTypeFlag,
+ DataType (cBlockArea::*Fn)(int, int, int) const
+>
+static int GetRelBlock(lua_State * a_LuaState)
+{
+ // Check the common params:
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ // Read the common params:
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the 'self' param.");
+ }
+
+ // Check the datatype's presence:
+ if ((self->GetDataTypes() & DataTypeFlag) == 0)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The area doesn't contain the datatype (%d).", DataTypeFlag);
+ }
+
+ // Read the overloaded params:
+ Vector3i coords;
+ readVector3iOverloadParams(L, 2, coords, "coords");
+ if (!self->IsValidRelCoords(coords))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The coords ({%d, %d, %d}) are out of range ({%d, %d, %d}).",
+ coords.x, coords.y, coords.z,
+ self->GetSizeX(), self->GetSizeY(), self->GetSizeZ()
+ );
+ }
+
+ // Get the block info:
+ L.Push((self->*Fn)(coords.x, coords.y, coords.z));
+ return 0;
+}
+
+
+
+
+
+/** Templated bindings for the SetBlock___() functions.
+DataType is either BLOCKTYPE or NIBBLETYPE.
+DataTypeFlag is the ba___ constant used for the datatypebeing manipulated.
+Fn is the setter function.
+Also supports the Vector3i overloads (TODO: document these (?)). */
+template <
+ typename DataType,
+ int DataTypeFlag,
+ void (cBlockArea::*Fn)(int, int, int, DataType)
+>
+static int SetBlock(lua_State * a_LuaState)
+{
+ // Check the common params:
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ // Read the common params:
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the 'self' param.");
+ }
+
+ // Check the datatype's presence:
+ if ((self->GetDataTypes() & DataTypeFlag) == 0)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The area doesn't contain the datatype (%d).", DataTypeFlag);
+ }
+
+ // Read the overloaded params:
+ Vector3i coords;
+ auto idx = readVector3iOverloadParams(L, 2, coords, "coords");
+ if (!self->IsValidCoords(coords))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The coords ({%d, %d, %d}) are out of range ({%d, %d, %d} - {%d, %d, %d}).",
+ coords.x, coords.y, coords.z,
+ self->GetOriginX(), self->GetOriginY(), self->GetOriginZ(),
+ self->GetOriginX() + self->GetSizeX() - 1, self->GetOriginY() + self->GetSizeY() - 1, self->GetOriginZ() + self->GetSizeZ() - 1
+ );
+ }
+ DataType data;
+ L.GetStackValues(idx, data);
+
+ // Set the block info:
+ (self->*Fn)(coords.x, coords.y, coords.z, data);
+ return 0;
+}
+
+
+
+
+
+/** Templated bindings for the SetRelBlock___() functions.
+DataType is either BLOCKTYPE or NIBBLETYPE.
+DataTypeFlag is the ba___ constant used for the datatypebeing manipulated.
+Fn is the setter function.
+Also supports the Vector3i overloads (TODO: document these (?)). */
+template <
+ typename DataType,
+ int DataTypeFlag,
+ void (cBlockArea::*Fn)(int, int, int, DataType)
+>
+static int SetRelBlock(lua_State * a_LuaState)
+{
+ // Check the common params:
+ cLuaState L(a_LuaState);
+ if (!L.CheckParamSelf("cBlockArea"))
+ {
+ return 0;
+ }
+
+ // Read the common params:
+ cBlockArea * self;
+ if (!L.GetStackValues(1, self))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "Cannot read the 'self' param.");
+ }
+
+ // Check the datatype's presence:
+ if ((self->GetDataTypes() & DataTypeFlag) == 0)
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The area doesn't contain the datatype (%d).", DataTypeFlag);
+ }
+
+ // Read the overloaded params:
+ Vector3i coords;
+ auto idx = readVector3iOverloadParams(L, 2, coords, "coords");
+ if (!self->IsValidRelCoords(coords))
+ {
+ return cManualBindings::ApiParamError(a_LuaState, "The coords ({%d, %d, %d}) are out of range ({%d, %d, %d}).",
+ coords.x, coords.y, coords.z,
+ self->GetSizeX(), self->GetSizeY(), self->GetSizeZ()
+ );
+ }
+ DataType data;
+ L.GetStackValues(idx, data);
+
+ // Set the block info:
+ (self->*Fn)(coords.x, coords.y, coords.z, data);
+ return 0;
+}
+
+
+
+
+
+void cManualBindings::BindBlockArea(lua_State * a_LuaState)
+{
+ tolua_beginmodule(a_LuaState, nullptr);
+ tolua_beginmodule(a_LuaState, "cBlockArea");
+ tolua_function(a_LuaState, "Create", tolua_cBlockArea_Create);
+ tolua_function(a_LuaState, "DoWithBlockEntityAt", DoWithXYZ<cBlockArea, cBlockEntity, &cBlockArea::DoWithBlockEntityAt, &cBlockArea::IsValidCoords>);
+ tolua_function(a_LuaState, "DoWithBlockEntityRelAt", DoWithXYZ<cBlockArea, cBlockEntity, &cBlockArea::DoWithBlockEntityRelAt, &cBlockArea::IsValidRelCoords>);
+ tolua_function(a_LuaState, "FillRelCuboid", tolua_cBlockArea_FillRelCuboid);
+ tolua_function(a_LuaState, "ForEachBlockEntity", ForEach< cBlockArea, cBlockEntity, &cBlockArea::ForEachBlockEntity>);
+ tolua_function(a_LuaState, "GetBlockLight", GetBlock<NIBBLETYPE, cBlockArea::baLight, &cBlockArea::GetRelBlockLight>);
+ tolua_function(a_LuaState, "GetBlockMeta", GetBlock<NIBBLETYPE, cBlockArea::baMetas, &cBlockArea::GetRelBlockMeta>);
+ tolua_function(a_LuaState, "GetBlockSkyLight", GetBlock<NIBBLETYPE, cBlockArea::baSkyLight, &cBlockArea::GetRelBlockSkyLight>);
+ tolua_function(a_LuaState, "GetBlockType", GetBlock<BLOCKTYPE, cBlockArea::baTypes, &cBlockArea::GetRelBlockType>);
+ tolua_function(a_LuaState, "GetBlockTypeMeta", tolua_cBlockArea_GetBlockTypeMeta);
+ tolua_function(a_LuaState, "GetCoordRange", tolua_cBlockArea_GetCoordRange);
+ tolua_function(a_LuaState, "GetNonAirCropRelCoords", tolua_cBlockArea_GetNonAirCropRelCoords);
+ tolua_function(a_LuaState, "GetOrigin", tolua_cBlockArea_GetOrigin);
+ tolua_function(a_LuaState, "GetRelBlockLight", GetRelBlock<NIBBLETYPE, cBlockArea::baLight, &cBlockArea::GetRelBlockLight>);
+ tolua_function(a_LuaState, "GetRelBlockMeta", GetRelBlock<NIBBLETYPE, cBlockArea::baMetas, &cBlockArea::GetRelBlockMeta>);
+ tolua_function(a_LuaState, "GetRelBlockSkyLight", GetRelBlock<NIBBLETYPE, cBlockArea::baSkyLight, &cBlockArea::GetRelBlockSkyLight>);
+ tolua_function(a_LuaState, "GetRelBlockType", GetRelBlock<BLOCKTYPE, cBlockArea::baTypes, &cBlockArea::GetRelBlockType>);
+ tolua_function(a_LuaState, "GetRelBlockTypeMeta", tolua_cBlockArea_GetRelBlockTypeMeta);
+ tolua_function(a_LuaState, "GetSize", tolua_cBlockArea_GetSize);
+ tolua_function(a_LuaState, "LoadFromSchematicFile", tolua_cBlockArea_LoadFromSchematicFile);
+ tolua_function(a_LuaState, "LoadFromSchematicString", tolua_cBlockArea_LoadFromSchematicString);
+ tolua_function(a_LuaState, "Read", tolua_cBlockArea_Read);
+ tolua_function(a_LuaState, "RelLine", tolua_cBlockArea_RelLine);
+ tolua_function(a_LuaState, "SaveToSchematicFile", tolua_cBlockArea_SaveToSchematicFile);
+ tolua_function(a_LuaState, "SaveToSchematicString", tolua_cBlockArea_SaveToSchematicString);
+ tolua_function(a_LuaState, "SetBlockType", SetBlock<BLOCKTYPE, cBlockArea::baTypes, &cBlockArea::SetRelBlockType>);
+ tolua_function(a_LuaState, "SetBlockMeta", SetBlock<NIBBLETYPE, cBlockArea::baMetas, &cBlockArea::SetRelBlockMeta>);
+ tolua_function(a_LuaState, "SetBlockLight", SetBlock<NIBBLETYPE, cBlockArea::baLight, &cBlockArea::SetRelBlockLight>);
+ tolua_function(a_LuaState, "SetBlockSkyLight", SetBlock<NIBBLETYPE, cBlockArea::baSkyLight, &cBlockArea::SetRelBlockSkyLight>);
+ tolua_function(a_LuaState, "SetRelBlockType", SetRelBlock<BLOCKTYPE, cBlockArea::baTypes, &cBlockArea::SetRelBlockType>);
+ tolua_function(a_LuaState, "SetRelBlockMeta", SetRelBlock<NIBBLETYPE, cBlockArea::baMetas, &cBlockArea::SetRelBlockMeta>);
+ tolua_function(a_LuaState, "SetRelBlockLight", SetRelBlock<NIBBLETYPE, cBlockArea::baLight, &cBlockArea::SetRelBlockLight>);
+ tolua_function(a_LuaState, "SetRelBlockSkyLight", SetRelBlock<NIBBLETYPE, cBlockArea::baSkyLight, &cBlockArea::SetRelBlockSkyLight>);
+ tolua_function(a_LuaState, "Write", tolua_cBlockArea_Write);
+ tolua_endmodule(a_LuaState);
+ tolua_endmodule(a_LuaState);
+}
+
+
+
+