cBlockArea can now be loaded from a .schematic file.
git-svn-id: http://mc-server.googlecode.com/svn/trunk@1195 0a769ca7-a7f5-676a-18bf-c427514a06d6master
parent
a091413125
commit
afdbb1d71b
|
@ -69,6 +69,7 @@ function OnPlayerUsingItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, C
|
|||
|
||||
local HeldItem = Player:GetEquippedItem();
|
||||
|
||||
|
||||
if (HeldItem.m_ItemType == E_ITEM_STICK) then
|
||||
-- Magic sTick of ticking: set the pointed block for ticking at the next tick
|
||||
Player:SendMessage(cChatColor.LightGray .. "Setting next block tick to {" .. BlockX .. ", " .. BlockY .. ", " .. BlockZ .. "}")
|
||||
|
@ -76,6 +77,7 @@ function OnPlayerUsingItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, C
|
|||
return true
|
||||
end
|
||||
|
||||
|
||||
if (HeldItem.m_ItemType == E_ITEM_BLAZE_ROD) then
|
||||
-- Magic rod of query: show block types and metas for both neighbors of the pointed face
|
||||
local Type = 0;
|
||||
|
@ -104,6 +106,7 @@ function OnPlayerUsingItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, C
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
-- Rclk with a diamond to read a block area, dump it, crop it, dump it again, crop it again...
|
||||
if (Player:GetEquippedItem().m_ItemType == E_ITEM_DIAMOND) then
|
||||
local Area = cBlockArea();
|
||||
|
@ -132,6 +135,20 @@ function OnPlayerUsingItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, C
|
|||
return false;
|
||||
end
|
||||
|
||||
|
||||
-- Rclk with an eye of ender places a predefined schematic at the cursor
|
||||
if (Player:GetEquippedItem().m_ItemType == E_ITEM_EYE_OF_ENDER) then
|
||||
local Area = cBlockArea();
|
||||
if not(Area:LoadFromSchematicFile("schematics/test.schematic")) then
|
||||
LOG("Loading failed");
|
||||
return false;
|
||||
end
|
||||
LOG("Schematic loaded, placing now.");
|
||||
Area:Write(Player:GetWorld(), BlockX, BlockY, BlockZ);
|
||||
LOG("Done.");
|
||||
return false;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Lua binding: AllToLua
|
||||
** Generated automatically by tolua++-1.0.92 on 02/06/13 17:53:00.
|
||||
** Generated automatically by tolua++-1.0.92 on 02/06/13 22:02:40.
|
||||
*/
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
@ -17859,6 +17859,41 @@ static int tolua_AllToLua_cBlockArea_DumpToRawFile00(lua_State* tolua_S)
|
|||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: LoadFromSchematicFile of class cBlockArea */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_LoadFromSchematicFile00
|
||||
static int tolua_AllToLua_cBlockArea_LoadFromSchematicFile00(lua_State* tolua_S)
|
||||
{
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_Error tolua_err;
|
||||
if (
|
||||
!tolua_isusertype(tolua_S,1,"cBlockArea",0,&tolua_err) ||
|
||||
!tolua_iscppstring(tolua_S,2,0,&tolua_err) ||
|
||||
!tolua_isnoobj(tolua_S,3,&tolua_err)
|
||||
)
|
||||
goto tolua_lerror;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
cBlockArea* self = (cBlockArea*) tolua_tousertype(tolua_S,1,0);
|
||||
const AString a_FileName = ((const AString) tolua_tocppstring(tolua_S,2,0));
|
||||
#ifndef TOLUA_RELEASE
|
||||
if (!self) tolua_error(tolua_S,"invalid 'self' in function 'LoadFromSchematicFile'", NULL);
|
||||
#endif
|
||||
{
|
||||
bool tolua_ret = (bool) self->LoadFromSchematicFile(a_FileName);
|
||||
tolua_pushboolean(tolua_S,(bool)tolua_ret);
|
||||
tolua_pushcppstring(tolua_S,(const char*)a_FileName);
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
#ifndef TOLUA_RELEASE
|
||||
tolua_lerror:
|
||||
tolua_error(tolua_S,"#ferror in function 'LoadFromSchematicFile'.",&tolua_err);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif //#ifndef TOLUA_DISABLE
|
||||
|
||||
/* method: Crop of class cBlockArea */
|
||||
#ifndef TOLUA_DISABLE_tolua_AllToLua_cBlockArea_Crop00
|
||||
static int tolua_AllToLua_cBlockArea_Crop00(lua_State* tolua_S)
|
||||
|
@ -21740,6 +21775,7 @@ TOLUA_API int tolua_AllToLua_open (lua_State* tolua_S)
|
|||
tolua_function(tolua_S,"Write",tolua_AllToLua_cBlockArea_Write00);
|
||||
tolua_function(tolua_S,"Write",tolua_AllToLua_cBlockArea_Write01);
|
||||
tolua_function(tolua_S,"DumpToRawFile",tolua_AllToLua_cBlockArea_DumpToRawFile00);
|
||||
tolua_function(tolua_S,"LoadFromSchematicFile",tolua_AllToLua_cBlockArea_LoadFromSchematicFile00);
|
||||
tolua_function(tolua_S,"Crop",tolua_AllToLua_cBlockArea_Crop00);
|
||||
tolua_function(tolua_S,"SetRelBlockType",tolua_AllToLua_cBlockArea_SetRelBlockType00);
|
||||
tolua_function(tolua_S,"SetBlockType",tolua_AllToLua_cBlockArea_SetBlockType00);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
** Lua binding: AllToLua
|
||||
** Generated automatically by tolua++-1.0.92 on 02/06/13 17:53:01.
|
||||
** Generated automatically by tolua++-1.0.92 on 02/06/13 22:02:40.
|
||||
*/
|
||||
|
||||
/* Exported function */
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "Globals.h"
|
||||
#include "BlockArea.h"
|
||||
#include "World.h"
|
||||
#include "zlib.h"
|
||||
#include "WorldStorage/FastNBT.h"
|
||||
|
||||
|
||||
|
||||
|
@ -188,6 +190,46 @@ void cBlockArea::DumpToRawFile(const AString & a_FileName)
|
|||
|
||||
|
||||
|
||||
bool cBlockArea::LoadFromSchematicFile(const AString & a_FileName)
|
||||
{
|
||||
// Un-GZip the contents:
|
||||
AString Contents;
|
||||
gzFile File = gzopen(a_FileName.c_str(), "rb");
|
||||
if (File == NULL)
|
||||
{
|
||||
LOG("Cannot open the schematic file \"%s\".", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
// Since the gzip format doesn't really support getting the uncompressed length, we need to read incrementally. Yuck!
|
||||
int NumBytesRead = 0;
|
||||
char Buffer[32 KiB];
|
||||
while ((NumBytesRead = gzread(File, Buffer, sizeof(Buffer))) > 0)
|
||||
{
|
||||
Contents.append(Buffer, NumBytesRead);
|
||||
}
|
||||
if (NumBytesRead < 0)
|
||||
{
|
||||
LOG("Cannot read GZipped data in the schematic file \"%s\", error %d", a_FileName.c_str(), NumBytesRead);
|
||||
gzclose(File);
|
||||
return false;
|
||||
}
|
||||
gzclose(File);
|
||||
|
||||
// TODO: Parse the NBT:
|
||||
cParsedNBT NBT(Contents.data(), Contents.size());
|
||||
if (!NBT.IsValid())
|
||||
{
|
||||
LOG("Cannot parse the NBT in the schematic file \"%s\".", a_FileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
return LoadFromSchematicNBT(NBT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void cBlockArea::Crop(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ)
|
||||
{
|
||||
if (HasBlockTypes())
|
||||
|
@ -799,3 +841,83 @@ void cBlockArea::CropNibbles(NIBBLEARRAY & a_Array, int a_AddMinX, int a_SubMaxX
|
|||
|
||||
|
||||
|
||||
|
||||
bool cBlockArea::LoadFromSchematicNBT(cParsedNBT & a_NBT)
|
||||
{
|
||||
int TMaterials = a_NBT.FindChildByName(a_NBT.GetRoot(), "Materials");
|
||||
if ((TMaterials > 0) && (a_NBT.GetType(TMaterials) == TAG_String))
|
||||
{
|
||||
AString Materials = a_NBT.GetString(TMaterials);
|
||||
if (Materials.compare("Alpha") != 0)
|
||||
{
|
||||
LOG("Materials tag is present and \"%s\" instead of \"Alpha\". Possibly a wrong-format schematic file.", Materials.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
int TSizeX = a_NBT.FindChildByName(a_NBT.GetRoot(), "Width");
|
||||
int TSizeY = a_NBT.FindChildByName(a_NBT.GetRoot(), "Height");
|
||||
int TSizeZ = a_NBT.FindChildByName(a_NBT.GetRoot(), "Length");
|
||||
if (
|
||||
(TSizeX < 0) || (TSizeY < 0) || (TSizeZ < 0) ||
|
||||
(a_NBT.GetType(TSizeX) != TAG_Short) ||
|
||||
(a_NBT.GetType(TSizeY) != TAG_Short) ||
|
||||
(a_NBT.GetType(TSizeZ) != TAG_Short)
|
||||
)
|
||||
{
|
||||
LOG("Dimensions are missing from the schematic file (%d, %d, %d), (%d, %d, %d)",
|
||||
TSizeX, TSizeY, TSizeZ,
|
||||
a_NBT.GetType(TSizeX), a_NBT.GetType(TSizeY), a_NBT.GetType(TSizeZ)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
int SizeX = a_NBT.GetShort(TSizeX);
|
||||
int SizeY = a_NBT.GetShort(TSizeY);
|
||||
int SizeZ = a_NBT.GetShort(TSizeZ);
|
||||
if ((SizeX < 1) || (SizeY < 1) || (SizeZ < 1))
|
||||
{
|
||||
LOG("Dimensions are invalid in the schematic file: %d, %d, %d", SizeX, SizeY, SizeZ);
|
||||
return false;
|
||||
}
|
||||
|
||||
int TBlockTypes = a_NBT.FindChildByName(a_NBT.GetRoot(), "Blocks");
|
||||
int TBlockMetas = a_NBT.FindChildByName(a_NBT.GetRoot(), "Data");
|
||||
if ((TBlockTypes < 0) || (a_NBT.GetType(TBlockTypes) != TAG_ByteArray))
|
||||
{
|
||||
LOG("BlockTypes are invalid in the schematic file: %d", TBlockTypes);
|
||||
return false;
|
||||
}
|
||||
bool AreMetasPresent = (TBlockMetas > 0) && (a_NBT.GetType(TBlockMetas) == TAG_ByteArray);
|
||||
|
||||
SetSize(SizeX, SizeY, SizeZ, AreMetasPresent ? (baTypes | baMetas) : baTypes);
|
||||
|
||||
// Copy the block types and metas:
|
||||
int NumBytes = m_SizeX * m_SizeY * m_SizeZ;
|
||||
if (a_NBT.GetDataLength(TBlockTypes) < NumBytes)
|
||||
{
|
||||
LOG("BlockTypes truncated in the schematic file (exp %d, got %d bytes). Loading partial.",
|
||||
NumBytes, a_NBT.GetDataLength(TBlockTypes)
|
||||
);
|
||||
NumBytes = a_NBT.GetDataLength(TBlockTypes);
|
||||
}
|
||||
memcpy(m_BlockTypes, a_NBT.GetData(TBlockTypes), NumBytes);
|
||||
|
||||
if (AreMetasPresent)
|
||||
{
|
||||
int NumBytes = m_SizeX * m_SizeY * m_SizeZ;
|
||||
if (a_NBT.GetDataLength(TBlockMetas) < NumBytes)
|
||||
{
|
||||
LOG("BlockMetas truncated in the schematic file (exp %d, got %d bytes). Loading partial.",
|
||||
NumBytes, a_NBT.GetDataLength(TBlockMetas)
|
||||
);
|
||||
NumBytes = a_NBT.GetDataLength(TBlockMetas);
|
||||
}
|
||||
memcpy(m_BlockMetas, a_NBT.GetData(TBlockMetas), NumBytes);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -16,9 +16,12 @@
|
|||
|
||||
|
||||
|
||||
// fwd: "cWorld.h"
|
||||
// fwd: World.h
|
||||
class cWorld;
|
||||
|
||||
// fwd: FastNBT.h
|
||||
class cParsedNBT;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -59,6 +62,9 @@ public:
|
|||
// TODO: Write() is not too good an interface: if it fails, there's no way to repeat only for the parts that didn't write
|
||||
// A better way may be to return a list of cBlockAreas for each part that didn't succeed writing, so that the caller may try again
|
||||
|
||||
/// Loads an area from a .schematic file. Returns true if successful
|
||||
bool LoadFromSchematicFile(const AString & a_FileName);
|
||||
|
||||
/// Crops the internal contents by the specified amount of blocks from each border.
|
||||
void Crop(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ);
|
||||
|
||||
|
@ -166,6 +172,9 @@ protected:
|
|||
// Crop helpers:
|
||||
void CropBlockTypes(int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ);
|
||||
void CropNibbles (NIBBLEARRAY & a_Array, int a_AddMinX, int a_SubMaxX, int a_AddMinY, int a_SubMaxY, int a_AddMinZ, int a_SubMaxZ);
|
||||
|
||||
/// Loads the area from a schematic file uncompressed and parsed into a NBT tree. Returns true if successful.
|
||||
bool LoadFromSchematicNBT(cParsedNBT & a_NBT);
|
||||
|
||||
// tolua_begin
|
||||
} ;
|
||||
|
|
Loading…
Reference in New Issue