diff options
author | Mattes D <github@xoft.cz> | 2017-06-24 11:58:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-24 11:58:06 +0200 |
commit | fe4253834919d6c742c59c701d3d5ce8285f4504 (patch) | |
tree | c201ca7a02344029679d4addffb695a3d20c4bec /src/Bindings/ManualBindings_BlockArea.cpp | |
parent | Load entities from old and new names (diff) | |
download | cuberite-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 '')
-rw-r--r-- | src/Bindings/ManualBindings_BlockArea.cpp | 998 |
1 files changed, 998 insertions, 0 deletions
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); +} + + + + |