Ejemplo n.º 1
0
bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
{
    double Pos[3];
    if (!LoadDoublesListFromNBT(Pos, 3, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Pos")))
    {
        return false;
    }
    a_Entity.SetPosition(Pos[0], Pos[1], Pos[2]);

    double Speed[3];
    if (!LoadDoublesListFromNBT(Speed, 3, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Motion")))
    {
        return false;
    }
    a_Entity.SetSpeed(Speed[0], Speed[1], Speed[2]);

    double Rotation[3];
    if (!LoadDoublesListFromNBT(Rotation, 2, a_NBT, a_NBT.FindChildByName(a_TagIdx, "Rotation")))
    {
        return false;
    }
    a_Entity.SetRotation(Rotation[0]);
    a_Entity.SetRoll    (Rotation[1]);

    return true;
}
Ejemplo n.º 2
0
void cWSSAnvil::CopyNBTData(const cParsedNBT & a_NBT, int a_Tag, const AString & a_ChildName, char * a_Destination, int a_Length)
{
    int Child = a_NBT.FindChildByName(a_Tag, a_ChildName);
    if ((Child >= 0) && (a_NBT.GetType(Child) == TAG_ByteArray) && (a_NBT.GetDataLength(Child) == a_Length))
    {
        memcpy(a_Destination, a_NBT.GetData(Child), a_Length);
    }
}
Ejemplo n.º 3
0
bool cWSSAnvil::LoadDoublesListFromNBT(double * a_Doubles, int a_NumDoubles, const cParsedNBT & a_NBT, int a_TagIdx)
{
    if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List) || (a_NBT.GetChildrenType(a_TagIdx) != TAG_Double))
    {
        return false;
    }
    int idx = 0;
    for (int Tag = a_NBT.GetFirstChild(a_TagIdx); (Tag > 0) && (idx < a_NumDoubles); Tag = a_NBT.GetNextSibling(Tag), ++idx)
    {
        a_Doubles[idx] = a_NBT.GetDouble(Tag);
    }  // for Tag - PosTag[]
    return (idx == a_NumDoubles);  // Did we read enough doubles?
}
Ejemplo n.º 4
0
void cWSSAnvil::LoadJukeboxFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
{
    ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
    int x, y, z;
    if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
    {
        return;
    }
    std::auto_ptr<cJukeboxEntity> Jukebox(new cJukeboxEntity(x, y, z, m_World));
    int Record = a_NBT.FindChildByName(a_TagIdx, "Record");
    if (Record >= 0)
    {
        Jukebox->SetRecord(a_NBT.GetInt(Record));
    }
    a_BlockEntities.push_back(Jukebox.release());
}
Ejemplo n.º 5
0
void cWSSAnvil::LoadNoteFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
{
    ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
    int x, y, z;
    if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
    {
        return;
    }
    std::auto_ptr<cNoteEntity> Note(new cNoteEntity(x, y, z, m_World));
    int note = a_NBT.FindChildByName(a_TagIdx, "note");
    if (note >= 0)
    {
        Note->SetPitch(a_NBT.GetByte(note));
    }
    a_BlockEntities.push_back(Note.release());
}
Ejemplo n.º 6
0
void cWSSAnvil::LoadHopperFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
{
    ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
    int x, y, z;
    if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
    {
        return;
    }
    int Items = a_NBT.FindChildByName(a_TagIdx, "Items");
    if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List))
    {
        return;  // Make it an empty hopper - the chunk loader will provide an empty cHopperEntity for this
    }
    std::auto_ptr<cHopperEntity> Hopper(new cHopperEntity(x, y, z, m_World));
    LoadItemGridFromNBT(Hopper->GetContents(), a_NBT, Items);
    a_BlockEntities.push_back(Hopper.release());
}
Ejemplo n.º 7
0
void cWSSAnvil::LoadMinecartCFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
    int Items = a_NBT.FindChildByName(a_TagIdx, "Items");
    if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List))
    {
        return;  // Make it an empty chest - the chunk loader will provide an empty cChestEntity for this
    }
    std::auto_ptr<cMinecartWithChest> Minecart(new cMinecartWithChest(0, 0, 0));
    if (!LoadEntityBaseFromNBT(*Minecart.get(), a_NBT, a_TagIdx))
    {
        return;
    }
    for (int Child = a_NBT.GetFirstChild(Items); Child != -1; Child = a_NBT.GetNextSibling(Child))
    {
        int Slot = a_NBT.FindChildByName(Child, "Slot");
        if ((Slot < 0) || (a_NBT.GetType(Slot) != TAG_Byte))
        {
            continue;
        }
        cItem Item;
        if (LoadItemFromNBT(Item, a_NBT, Child))
        {
            Minecart->SetSlot(a_NBT.GetByte(Slot), Item);
        }
    }  // for itr - ItemDefs[]
    a_Entities.push_back(Minecart.release());
}
Ejemplo n.º 8
0
bool cWSSAnvil::LoadProjectileBaseFromNBT(cProjectileEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
{
    if (!LoadEntityBaseFromNBT(a_Entity, a_NBT, a_TagIdx))
    {
        return false;
    }

    bool IsInGround = false;
    int InGroundIdx = a_NBT.FindChildByName(a_TagIdx, "inGround");
    if (InGroundIdx > 0)
    {
        IsInGround = (a_NBT.GetByte(InGroundIdx) != 0);
    }
    a_Entity.SetIsInGround(IsInGround);

    // TODO: Load inTile, TileCoords

    return true;
}
Ejemplo n.º 9
0
void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
    int ItemTag = a_NBT.FindChildByName(a_TagIdx, "Item");
    if ((ItemTag < 0) || (a_NBT.GetType(ItemTag) != TAG_Compound))
    {
        return;
    }
    cItem Item;
    if (!LoadItemFromNBT(Item, a_NBT, ItemTag))
    {
        return;
    }
    std::auto_ptr<cPickup> Pickup(new cPickup(0, 0, 0, Item, false)); // Pickup delay doesn't matter, just say false
    if (!LoadEntityBaseFromNBT(*Pickup.get(), a_NBT, a_TagIdx))
    {
        return;
    }
    a_Entities.push_back(Pickup.release());
}
Ejemplo n.º 10
0
void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
    std::auto_ptr<cArrowEntity> Arrow(new cArrowEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0)));
    if (!LoadProjectileBaseFromNBT(*Arrow.get(), a_NBT, a_TagIdx))
    {
        return;
    }

    // Load pickup state:
    int PickupIdx = a_NBT.FindChildByName(a_TagIdx, "pickup");
    if (PickupIdx > 0)
    {
        Arrow->SetPickupState((cArrowEntity::ePickupState)a_NBT.GetByte(PickupIdx));
    }
    else
    {
        // Try the older "player" tag:
        int PlayerIdx = a_NBT.FindChildByName(a_TagIdx, "player");
        if (PlayerIdx > 0)
        {
            Arrow->SetPickupState((a_NBT.GetByte(PlayerIdx) == 0) ? cArrowEntity::psNoPickup : cArrowEntity::psInSurvivalOrCreative);
        }
    }

    // Load damage:
    int DamageIdx = a_NBT.FindChildByName(a_TagIdx, "damage");
    if (DamageIdx > 0)
    {
        Arrow->SetDamageCoeff(a_NBT.GetDouble(DamageIdx));
    }

    // Store the new arrow in the entities list:
    a_Entities.push_back(Arrow.release());
}
Ejemplo n.º 11
0
void cWSSAnvil::LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a_NBT, int a_ItemsTagIdx, int a_SlotOffset)
{
    int NumSlots = a_ItemGrid.GetNumSlots();
    for (int Child = a_NBT.GetFirstChild(a_ItemsTagIdx); Child != -1; Child = a_NBT.GetNextSibling(Child))
    {
        int SlotTag = a_NBT.FindChildByName(Child, "Slot");
        if ((SlotTag < 0) || (a_NBT.GetType(SlotTag) != TAG_Byte))
        {
            continue;
        }
        int SlotNum = (int)(a_NBT.GetByte(SlotTag)) - a_SlotOffset;
        if ((SlotNum < 0) || (SlotNum >= NumSlots))
        {
            // SlotNum outside of the range
            continue;
        }
        cItem Item;
        if (LoadItemFromNBT(Item, a_NBT, Child))
        {
            a_ItemGrid.SetSlot(SlotNum, Item);
        }
    }  // for itr - ItemDefs[]
}
Ejemplo n.º 12
0
void cWSSAnvil::LoadSignFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
{
    ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
    int x, y, z;
    if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
    {
        return;
    }
    std::auto_ptr<cSignEntity> Sign(new cSignEntity(E_BLOCK_SIGN_POST, x, y, z, m_World));

    int currentLine = a_NBT.FindChildByName(a_TagIdx, "Text1");
    if (currentLine >= 0)
    {
        Sign->SetLine(0, a_NBT.GetString(currentLine));
    }

    currentLine = a_NBT.FindChildByName(a_TagIdx, "Text2");
    if (currentLine >= 0)
    {
        Sign->SetLine(1, a_NBT.GetString(currentLine));
    }

    currentLine = a_NBT.FindChildByName(a_TagIdx, "Text3");
    if (currentLine >= 0)
    {
        Sign->SetLine(2, a_NBT.GetString(currentLine));
    }

    currentLine = a_NBT.FindChildByName(a_TagIdx, "Text4");
    if (currentLine >= 0)
    {
        Sign->SetLine(3, a_NBT.GetString(currentLine));
    }

    a_BlockEntities.push_back(Sign.release());
}
Ejemplo n.º 13
0
bool cWSSAnvil::GetBlockEntityNBTPos(const cParsedNBT & a_NBT, int a_TagIdx, int & a_X, int & a_Y, int & a_Z)
{
    int x = a_NBT.FindChildByName(a_TagIdx, "x");
    if ((x < 0) || (a_NBT.GetType(x) != TAG_Int))
    {
        return false;
    }
    int y = a_NBT.FindChildByName(a_TagIdx, "y");
    if ((y < 0) || (a_NBT.GetType(y) != TAG_Int))
    {
        return false;
    }
    int z = a_NBT.FindChildByName(a_TagIdx, "z");
    if ((z < 0) || (a_NBT.GetType(z) != TAG_Int))
    {
        return false;
    }
    a_X = a_NBT.GetInt(x);
    a_Y = a_NBT.GetInt(y);
    a_Z = a_NBT.GetInt(z);
    return true;
}
Ejemplo n.º 14
0
void cWSSAnvil::LoadEntitiesFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
{
    if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List))
    {
        return;
    }

    for (int Child = a_NBT.GetFirstChild(a_TagIdx); Child != -1; Child = a_NBT.GetNextSibling(Child))
    {
        if (a_NBT.GetType(Child) != TAG_Compound)
        {
            continue;
        }
        int sID = a_NBT.FindChildByName(Child, "id");
        if (sID < 0)
        {
            continue;
        }
        LoadEntityFromNBT(a_Entities, a_NBT, Child, a_NBT.GetData(sID), a_NBT.GetDataLength(sID));
    }  // for Child - a_NBT[]
}
Ejemplo n.º 15
0
bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT & a_NBT)
{
    // The data arrays, in MCA-native y/z/x ordering (will be reordered for the final chunk data)
    cChunkDef::BlockTypes   BlockTypes;
    cChunkDef::BlockNibbles MetaData;
    cChunkDef::BlockNibbles BlockLight;
    cChunkDef::BlockNibbles SkyLight;

    memset(BlockTypes, E_BLOCK_AIR, sizeof(BlockTypes));
    memset(MetaData,   0,           sizeof(MetaData));
    memset(SkyLight,   0xff,        sizeof(SkyLight));  // By default, data not present in the NBT means air, which means full skylight
    memset(BlockLight, 0x00,        sizeof(BlockLight));

    // Load the blockdata, blocklight and skylight:
    int Level = a_NBT.FindChildByName(0, "Level");
    if (Level < 0)
    {
        return false;
    }
    int Sections = a_NBT.FindChildByName(Level, "Sections");
    if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List) || (a_NBT.GetChildrenType(Sections) != TAG_Compound))
    {
        return false;
    }
    for (int Child = a_NBT.GetFirstChild(Sections); Child >= 0; Child = a_NBT.GetNextSibling(Child))
    {
        int y = 0;
        int SectionY = a_NBT.FindChildByName(Child, "Y");
        if ((SectionY < 0) || (a_NBT.GetType(SectionY) != TAG_Byte))
        {
            continue;
        }
        y = a_NBT.GetByte(SectionY);
        if ((y < 0) || (y > 15))
        {
            continue;
        }
        CopyNBTData(a_NBT, Child, "Blocks",     (char *)&(BlockTypes[y * 4096]), 4096);
        CopyNBTData(a_NBT, Child, "Data",       (char *)&(MetaData[y   * 2048]), 2048);
        CopyNBTData(a_NBT, Child, "SkyLight",   (char *)&(SkyLight[y   * 2048]), 2048);
        CopyNBTData(a_NBT, Child, "BlockLight", (char *)&(BlockLight[y * 2048]), 2048);
    }  // for itr - LevelSections[]

    // Load the biomes from NBT, if present and valid. First try MCS-style, then Vanilla-style:
    cChunkDef::BiomeMap BiomeMap;
    cChunkDef::BiomeMap * Biomes = LoadBiomeMapFromNBT(&BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "MCSBiomes"));
    if (Biomes == NULL)
    {
        // MCS-style biomes not available, load vanilla-style:
        Biomes = LoadVanillaBiomeMapFromNBT(&BiomeMap, a_NBT, a_NBT.FindChildByName(Level, "Biomes"));
    }

    // Load the entities from NBT:
    cEntityList      Entities;
    cBlockEntityList BlockEntities;
    LoadEntitiesFromNBT     (Entities,      a_NBT, a_NBT.FindChildByName(Level, "Entities"));
    LoadBlockEntitiesFromNBT(BlockEntities, a_NBT, a_NBT.FindChildByName(Level, "TileEntities"), BlockTypes, MetaData);

    bool IsLightValid = (a_NBT.FindChildByName(Level, "MCSIsLightValid") > 0);

    /*
    // Uncomment this block for really cool stuff :)
    // DEBUG magic: Invert the underground, so that we can see the MC generator in action :)
    bool ShouldInvert[cChunkDef::Width * cChunkDef::Width];
    memset(ShouldInvert, 0, sizeof(ShouldInvert));
    for (int y = cChunkDef::Height - 1; y >= 0; y--)
    {
    	for (int x = 0; x < cChunkDef::Width; x++) for (int z = 0; z < cChunkDef::Width; z++)
    	{
    		int Index = cChunkDef::MakeIndexNoCheck(x, y, z);
    		if (ShouldInvert[x + cChunkDef::Width * z])
    		{
    			BlockTypes[Index] = (BlockTypes[Index] == E_BLOCK_AIR) ? E_BLOCK_STONE : E_BLOCK_AIR;
    		}
    		else
    		{
    			switch (BlockTypes[Index])
    			{
    				case E_BLOCK_AIR:
    				case E_BLOCK_LEAVES:
    				{
    					// nothing needed
    					break;
    				}
    				default:
    				{
    					ShouldInvert[x + cChunkDef::Width * z] = true;
    				}
    			}
    			BlockTypes[Index] = E_BLOCK_AIR;
    		}
    	}
    }  // for y
    //*/

    m_World->SetChunkData(
        a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
        BlockTypes, MetaData,
        IsLightValid ? BlockLight : NULL,
        IsLightValid ? SkyLight : NULL,
        NULL, Biomes,
        Entities, BlockEntities,
        false
    );
    return true;
}
Ejemplo n.º 16
0
void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, int a_IDTagLength)
{
    if (strncmp(a_IDTag, "Boat", a_IDTagLength) == 0)
    {
        LoadBoatFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "FallingBlock", a_IDTagLength) == 0)
    {
        LoadFallingBlockFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "Minecart", a_IDTagLength) == 0)
    {
        // It is a minecart, old style, find out the type:
        int TypeTag = a_NBT.FindChildByName(a_EntityTagIdx, "Type");
        if ((TypeTag < 0) || (a_NBT.GetType(TypeTag) != TAG_Int))
        {
            return;
        }
        switch (a_NBT.GetInt(TypeTag))
        {
        case 0:
            LoadMinecartRFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
            break;  // Rideable minecart
        case 1:
            LoadMinecartCFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
            break;  // Minecart with chest
        case 2:
            LoadMinecartFFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
            break;  // Minecart with furnace
        case 3:
            LoadMinecartTFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
            break;  // Minecart with TNT
        case 4:
            LoadMinecartHFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
            break;  // Minecart with Hopper
        }
    }
    else if (strncmp(a_IDTag, "MinecartRideable", a_IDTagLength) == 0)
    {
        LoadMinecartRFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "MinecartChest", a_IDTagLength) == 0)
    {
        LoadMinecartCFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "MinecartFurnace", a_IDTagLength) == 0)
    {
        LoadMinecartFFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "MinecartTNT", a_IDTagLength) == 0)
    {
        LoadMinecartTFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "MinecartHopper", a_IDTagLength) == 0)
    {
        LoadMinecartHFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "Item", a_IDTagLength) == 0)
    {
        LoadPickupFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "Arrow", a_IDTagLength) == 0)
    {
        LoadArrowFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "Snowball", a_IDTagLength) == 0)
    {
        LoadSnowballFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "Egg", a_IDTagLength) == 0)
    {
        LoadEggFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "Fireball", a_IDTagLength) == 0)
    {
        LoadFireballFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "SmallFireball", a_IDTagLength) == 0)
    {
        LoadFireChargeFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    else if (strncmp(a_IDTag, "ThrownEnderpearl", a_IDTagLength) == 0)
    {
        LoadThrownEnderpearlFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
    }
    // TODO: other entities
}
Ejemplo n.º 17
0
void cWSSAnvil::LoadFurnaceFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE * a_BlockTypes, NIBBLETYPE * a_BlockMetas)
{
    ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
    int x, y, z;
    if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
    {
        return;
    }
    int Items = a_NBT.FindChildByName(a_TagIdx, "Items");
    if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List))
    {
        return;  // Make it an empty furnace - the chunk loader will provide an empty cFurnaceEntity for this
    }

    // Convert coords to relative:
    int RelX = x;
    int RelZ = z;
    int ChunkX, ChunkZ;
    cChunkDef::AbsoluteToRelative(RelX, y, RelZ, ChunkX, ChunkZ);

    // Create the furnace entity, with proper BlockType and BlockMeta info:
    BLOCKTYPE  BlockType = cChunkDef::GetBlock(a_BlockTypes, RelX, y, RelZ);
    NIBBLETYPE BlockMeta = cChunkDef::GetNibble(a_BlockMetas, RelX, y, RelZ);
    std::auto_ptr<cFurnaceEntity> Furnace(new cFurnaceEntity(x, y, z, BlockType, BlockMeta, m_World));

    // Load slots:
    for (int Child = a_NBT.GetFirstChild(Items); Child != -1; Child = a_NBT.GetNextSibling(Child))
    {
        int Slot = a_NBT.FindChildByName(Child, "Slot");
        if ((Slot < 0) || (a_NBT.GetType(Slot) != TAG_Byte))
        {
            continue;
        }
        cItem Item;
        if (LoadItemFromNBT(Item, a_NBT, Child))
        {
            Furnace->SetSlot(a_NBT.GetByte(Slot), Item);
        }
    }  // for itr - ItemDefs[]

    // Load burn time:
    int BurnTime = a_NBT.FindChildByName(a_TagIdx, "BurnTime");
    if (BurnTime >= 0)
    {
        Int16 bt = a_NBT.GetShort(BurnTime);
        // Anvil doesn't store the time that the fuel can burn. We simply "reset" the current value to be the 100%
        Furnace->SetBurnTimes(bt, 0);
    }

    // Load cook time:
    int CookTime = a_NBT.FindChildByName(a_TagIdx, "CookTime");
    if (CookTime >= 0)
    {
        Int16 ct = a_NBT.GetShort(CookTime);
        // Anvil doesn't store the time that an item takes to cook. We simply use the default - 10 seconds (200 ticks)
        Furnace->SetCookTimes(200, ct);
    }

    // Restart cooking:
    Furnace->ContinueCooking();
    a_BlockEntities.push_back(Furnace.release());
}
Ejemplo n.º 18
0
void cFireworkItem::ParseFromNBT(cFireworkItem & a_FireworkItem, const cParsedNBT & a_NBT, int a_TagIdx, const ENUM_ITEM_ID a_Type)
{
	if (a_TagIdx < 0)
	{
		return;
	}

	switch (a_Type)
	{
		case E_ITEM_FIREWORK_STAR:
		{
			for (int explosiontag = a_NBT.GetFirstChild(a_TagIdx); explosiontag >= 0; explosiontag = a_NBT.GetNextSibling(explosiontag))
			{
				eTagType TagType = a_NBT.GetType(explosiontag);
				if (TagType == TAG_Byte) // Custon name tag
				{
					AString ExplosionName = a_NBT.GetName(explosiontag);

					if (ExplosionName == "Flicker")
					{
						a_FireworkItem.m_HasFlicker = (a_NBT.GetByte(explosiontag) == 1);
					}
					else if (ExplosionName == "Trail")
					{
						a_FireworkItem.m_HasTrail = (a_NBT.GetByte(explosiontag) == 1);
					}
					else if (ExplosionName == "Type")
					{
						a_FireworkItem.m_Type = a_NBT.GetByte(explosiontag);
					}
				}
				else if (TagType == TAG_IntArray)
				{
					AString ExplosionName = a_NBT.GetName(explosiontag);

					if (ExplosionName == "Colors")
					{
						// Divide by four as data length returned in bytes
						int DataLength = a_NBT.GetDataLength(explosiontag);
						// round to the next highest multiple of four
						DataLength -= DataLength % 4; 
						if (DataLength == 0)
						{
							continue;
						}

						const char * ColourData = (a_NBT.GetData(explosiontag));
						for (int i = 0; i < DataLength; i += 4 /* Size of network int*/)
						{
							a_FireworkItem.m_Colours.push_back(GetBEInt(ColourData + i));
						}
					}
					else if (ExplosionName == "FadeColors")
					{
						int DataLength = a_NBT.GetDataLength(explosiontag) / 4;
						// round to the next highest multiple of four
						DataLength -= DataLength % 4; 
						if (DataLength == 0)
						{
							continue;
						}

						const char * FadeColourData = (a_NBT.GetData(explosiontag));
						for (int i = 0; i < DataLength; i += 4 /* Size of network int*/)
						{
							a_FireworkItem.m_FadeColours.push_back(GetBEInt(FadeColourData + i));
						}
					}
				}
			}
			break;
		}
		case E_ITEM_FIREWORK_ROCKET:
		{
			for (int fireworkstag = a_NBT.GetFirstChild(a_TagIdx); fireworkstag >= 0; fireworkstag = a_NBT.GetNextSibling(fireworkstag))
			{
				eTagType TagType = a_NBT.GetType(fireworkstag);
				if (TagType == TAG_Byte) // Custon name tag
				{
					if (a_NBT.GetName(fireworkstag) == "Flight")
					{
						a_FireworkItem.m_FlightTimeInTicks = a_NBT.GetByte(fireworkstag) * 20;
					}
				}
				else if ((TagType == TAG_List) && (a_NBT.GetName(fireworkstag) == "Explosions"))
				{
					int ExplosionsChild = a_NBT.GetFirstChild(fireworkstag);
					if ((a_NBT.GetType(ExplosionsChild) == TAG_Compound) && (a_NBT.GetName(ExplosionsChild).empty()))
					{
						ParseFromNBT(a_FireworkItem, a_NBT, ExplosionsChild, E_ITEM_FIREWORK_STAR);
					}
				}
			}
			break;
		}
		default: ASSERT(!"Unhandled firework item!"); break;
	}
}
Ejemplo n.º 19
0
bool cMapSerializer::LoadMapFromNBT(const cParsedNBT & a_NBT)
{
	int Data = a_NBT.FindChildByName(0, "data");
	if (Data < 0)
	{
		return false;
	}

	int CurrLine = a_NBT.FindChildByName(Data, "scale");
	if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Byte))
	{
		unsigned int Scale = (unsigned int)a_NBT.GetByte(CurrLine);
		m_Map->SetScale(Scale);
	}

	CurrLine = a_NBT.FindChildByName(Data, "dimension");
	if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Byte))
	{
		eDimension Dimension = (eDimension) a_NBT.GetByte(CurrLine);
		
		if (Dimension != m_Map->m_World->GetDimension())
		{
			// TODO 2014-03-20 xdot: We should store nether maps in nether worlds, e.t.c.
			return false;
		}
	}

	CurrLine = a_NBT.FindChildByName(Data, "width");
	if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Short))
	{
		unsigned int Width = (unsigned int)a_NBT.GetShort(CurrLine);
		if (Width != 128)
		{
			return false;
		}
		m_Map->m_Width = Width;
	}

	CurrLine = a_NBT.FindChildByName(Data, "height");
	if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Short))
	{
		unsigned int Height = (unsigned int)a_NBT.GetShort(CurrLine);
		if (Height >= 256)
		{
			return false;
		}
		m_Map->m_Height = Height;
	}

	CurrLine = a_NBT.FindChildByName(Data, "xCenter");
	if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
	{
		int CenterX = a_NBT.GetInt(CurrLine);
		m_Map->m_CenterX = CenterX;
	}

	CurrLine = a_NBT.FindChildByName(Data, "zCenter");
	if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
	{
		int CenterZ = a_NBT.GetInt(CurrLine);
		m_Map->m_CenterZ = CenterZ;
	}

	unsigned int NumPixels = m_Map->GetNumPixels();
	m_Map->m_Data.resize(NumPixels);

	CurrLine = a_NBT.FindChildByName(Data, "colors");
	if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_ByteArray))
	{
		memcpy(m_Map->m_Data.data(), a_NBT.GetData(CurrLine), NumPixels);
	}

	return true;
}
Ejemplo n.º 20
0
bool cScoreboardSerializer::LoadScoreboardFromNBT(const cParsedNBT & a_NBT)
{
	int Data = a_NBT.FindChildByName(0, "data");
	if (Data < 0)
	{
		return false;
	}

	int Objectives = a_NBT.FindChildByName(Data, "Objectives");
	if (Objectives < 0)
	{
		return false;
	}

	for (int Child = a_NBT.GetFirstChild(Objectives); Child >= 0; Child = a_NBT.GetNextSibling(Child))
	{
		AString CriteriaName, DisplayName, Name;

		int CurrLine = a_NBT.FindChildByName(Child, "CriteriaName");
		if (CurrLine >= 0)
		{
			CriteriaName = a_NBT.GetString(CurrLine);
		}

		CurrLine = a_NBT.FindChildByName(Child, "DisplayName");
		if (CurrLine >= 0)
		{
			DisplayName = a_NBT.GetString(CurrLine);
		}

		CurrLine = a_NBT.FindChildByName(Child, "Name");
		if (CurrLine >= 0)
		{
			Name = a_NBT.GetString(CurrLine);
		}

		cObjective::eType Type = cObjective::StringToType(CriteriaName);

		m_ScoreBoard->RegisterObjective(Name, DisplayName, Type);
	}

	int PlayerScores = a_NBT.FindChildByName(Data, "PlayerScores");
	if (PlayerScores < 0)
	{
		return false;
	}

	for (int Child = a_NBT.GetFirstChild(PlayerScores); Child >= 0; Child = a_NBT.GetNextSibling(Child))
	{
		AString Name, ObjectiveName;

		cObjective::Score Score = 0;

		int CurrLine = a_NBT.FindChildByName(Child, "Score");
		if (CurrLine >= 0)
		{
			Score = a_NBT.GetInt(CurrLine);
		}

		CurrLine = a_NBT.FindChildByName(Child, "Name");
		if (CurrLine >= 0)
		{
			Name = a_NBT.GetString(CurrLine);
		}

		CurrLine = a_NBT.FindChildByName(Child, "Objective");
		if (CurrLine >= 0)
		{
			ObjectiveName = a_NBT.GetString(CurrLine);
		}

		cObjective * Objective = m_ScoreBoard->GetObjective(ObjectiveName);

		if (Objective)
		{
			Objective->SetScore(Name, Score);
		}
	}

	int Teams = a_NBT.FindChildByName(Data, "Teams");
	if (Teams < 0)
	{
		return false;
	}

	for (int Child = a_NBT.GetFirstChild(Teams); Child >= 0; Child = a_NBT.GetNextSibling(Child))
	{
		AString Name, DisplayName, Prefix, Suffix;

		bool AllowsFriendlyFire = true, CanSeeFriendlyInvisible = false;

		int CurrLine = a_NBT.FindChildByName(Child, "Name");
		if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
		{
			Name = a_NBT.GetString(CurrLine);
		}

		CurrLine = a_NBT.FindChildByName(Child, "DisplayName");
		if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
		{
			DisplayName = a_NBT.GetString(CurrLine);
		}

		CurrLine = a_NBT.FindChildByName(Child, "Prefix");
		if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
		{
			Prefix = a_NBT.GetString(CurrLine);
		}

		CurrLine = a_NBT.FindChildByName(Child, "Suffix");
		if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_String))
		{
			Suffix = a_NBT.GetString(CurrLine);
		}

		CurrLine = a_NBT.FindChildByName(Child, "AllowFriendlyFire");
		if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
		{
			AllowsFriendlyFire = (a_NBT.GetInt(CurrLine) != 0);
		}

		CurrLine = a_NBT.FindChildByName(Child, "SeeFriendlyInvisibles");
		if ((CurrLine >= 0) && (a_NBT.GetType(CurrLine) == TAG_Int))
		{
			CanSeeFriendlyInvisible = (a_NBT.GetInt(CurrLine) != 0);
		}

		cTeam * Team = m_ScoreBoard->RegisterTeam(Name, DisplayName, Prefix, Suffix);

		Team->SetFriendlyFire(AllowsFriendlyFire);
		Team->SetCanSeeFriendlyInvisible(CanSeeFriendlyInvisible);

		int Players = a_NBT.FindChildByName(Child, "Players");
		if (Players < 0)
		{
			continue;
		}

		for (int ChildB = a_NBT.GetFirstChild(Players); ChildB >= 0; ChildB = a_NBT.GetNextSibling(ChildB))
		{
			Team->AddPlayer(a_NBT.GetString(ChildB));
		}
	}

	int DisplaySlots = a_NBT.FindChildByName(Data, "DisplaySlots");
	if (DisplaySlots < 0)
	{
		return false;
	}

	int CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_0");
	if (CurrLine >= 0)
	{
		AString Name = a_NBT.GetString(CurrLine);

		m_ScoreBoard->SetDisplay(Name, cScoreboard::dsList);
	}

	CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_1");
	if (CurrLine >= 0)
	{
		AString Name = a_NBT.GetString(CurrLine);

		m_ScoreBoard->SetDisplay(Name, cScoreboard::dsSidebar);
	}

	CurrLine = a_NBT.FindChildByName(DisplaySlots, "slot_2");
	if (CurrLine >= 0)
	{
		AString Name = a_NBT.GetString(CurrLine);

		m_ScoreBoard->SetDisplay(Name, cScoreboard::dsName);
	}

	return true;
}
Ejemplo n.º 21
0
void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE * a_BlockTypes, NIBBLETYPE * a_BlockMetas)
{
    if ((a_TagIdx < 0) || (a_NBT.GetType(a_TagIdx) != TAG_List))
    {
        return;
    }

    for (int Child = a_NBT.GetFirstChild(a_TagIdx); Child != -1; Child = a_NBT.GetNextSibling(Child))
    {
        if (a_NBT.GetType(Child) != TAG_Compound)
        {
            continue;
        }
        int sID = a_NBT.FindChildByName(Child, "id");
        if (sID < 0)
        {
            continue;
        }
        if (strncmp(a_NBT.GetData(sID), "Chest", a_NBT.GetDataLength(sID)) == 0)
        {
            LoadChestFromNBT(a_BlockEntities, a_NBT, Child);
        }
        else if (strncmp(a_NBT.GetData(sID), "Dropper", a_NBT.GetDataLength(sID)) == 0)
        {
            LoadDropperFromNBT(a_BlockEntities, a_NBT, Child);
        }
        else if (strncmp(a_NBT.GetData(sID), "Furnace", a_NBT.GetDataLength(sID)) == 0)
        {
            LoadFurnaceFromNBT(a_BlockEntities, a_NBT, Child, a_BlockTypes, a_BlockMetas);
        }
        else if (strncmp(a_NBT.GetData(sID), "Hopper", a_NBT.GetDataLength(sID)) == 0)
        {
            LoadHopperFromNBT(a_BlockEntities, a_NBT, Child);
        }
        else if (strncmp(a_NBT.GetData(sID), "Music", a_NBT.GetDataLength(sID)) == 0)
        {
            LoadNoteFromNBT(a_BlockEntities, a_NBT, Child);
        }
        else if (strncmp(a_NBT.GetData(sID), "RecordPlayer", a_NBT.GetDataLength(sID)) == 0)
        {
            LoadJukeboxFromNBT(a_BlockEntities, a_NBT, Child);
        }
        else if (strncmp(a_NBT.GetData(sID), "Sign", a_NBT.GetDataLength(sID)) == 0)
        {
            LoadSignFromNBT(a_BlockEntities, a_NBT, Child);
        }
        else if (strncmp(a_NBT.GetData(sID), "Trap", a_NBT.GetDataLength(sID)) == 0)
        {
            LoadDispenserFromNBT(a_BlockEntities, a_NBT, Child);
        }
        // TODO: Other block entities
    }  // for Child - tag children
}
Ejemplo n.º 22
0
void cEnchantments::ParseFromNBT(const cParsedNBT & a_NBT, int a_EnchListTagIdx)
{
	// Read the enchantments from the specified NBT list tag (ench or StoredEnchantments)

	// Verify that the tag is a list:
	if (a_NBT.GetType(a_EnchListTagIdx) != TAG_List)
	{
		LOGWARNING("%s: Invalid EnchListTag type: exp %d, got %d. Enchantments not parsed",
			__FUNCTION__, TAG_List, a_NBT.GetType(a_EnchListTagIdx)
		);
		ASSERT(!"Bad EnchListTag type");
		return;
	}
	
	// Verify that the list is of Compounds:
	if (a_NBT.GetChildrenType(a_EnchListTagIdx) != TAG_Compound)
	{
		LOGWARNING("%s: Invalid NBT list children type: exp %d, got %d. Enchantments not parsed",
			__FUNCTION__, TAG_Compound, a_NBT.GetChildrenType(a_EnchListTagIdx)
		);
		ASSERT(!"Bad EnchListTag children type");
		return;
	}
	
	Clear();
	
	// Iterate over all the compound children, parse an enchantment from each:
	for (int tag = a_NBT.GetFirstChild(a_EnchListTagIdx); tag >= 0; tag = a_NBT.GetNextSibling(tag))
	{
		// tag is the compound inside the "ench" list tag
		ASSERT(a_NBT.GetType(tag) == TAG_Compound);
		
		// Search for the id and lvl tags' values:
		int id = -1, lvl = -1;
		for (int ch = a_NBT.GetFirstChild(tag); ch >= 0; ch = a_NBT.GetNextSibling(ch))
		{
			if (a_NBT.GetType(ch) != TAG_Short)
			{
				continue;
			}
			if (a_NBT.GetName(ch) == "id")
			{
				id = a_NBT.GetShort(ch);
			}
			else if (a_NBT.GetName(ch) == "lvl")
			{
				lvl = a_NBT.GetShort(ch);
			}
		}  // for ch - children of the compound tag
		
		if ((id == -1) || (lvl <= 0))
		{
			// Failed to parse either the id or the lvl, skip this compound
			continue;
		}
		
		// Store the enchantment:
		m_Enchantments[id] = lvl;
	}  // for tag - children of the ench list tag
}
Ejemplo n.º 23
0
bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx)
{
    int ID = a_NBT.FindChildByName(a_TagIdx, "id");
    if ((ID < 0) || (a_NBT.GetType(ID) != TAG_Short))
    {
        return false;
    }
    a_Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID));

    int Damage = a_NBT.FindChildByName(a_TagIdx, "Damage");
    if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short))
    {
        return false;
    }
    a_Item.m_ItemDamage = a_NBT.GetShort(Damage);

    int Count = a_NBT.FindChildByName(a_TagIdx, "Count");
    if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte))
    {
        return false;
    }
    a_Item.m_ItemCount = a_NBT.GetByte(Count);

    // Find the "tag" tag, used for enchantments and other extra data
    int TagTag = a_NBT.FindChildByName(a_TagIdx, "tag");
    if (TagTag <= 0)
    {
        // No extra data
        return true;
    }

    // Load enchantments:
    const char * EnchName = (a_Item.m_ItemType == E_ITEM_BOOK) ? "StoredEnchantments" : "ench";
    int EnchTag = a_NBT.FindChildByName(TagTag, EnchName);
    if (EnchTag > 0)
    {
        a_Item.m_Enchantments.ParseFromNBT(a_NBT, EnchTag);
    }

    return true;
}
Ejemplo n.º 24
0
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);
	
	Clear();
	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;
}
Ejemplo n.º 25
0
bool cSchematicFileSerializer::LoadFromSchematicNBT(cBlockArea & a_BlockArea, 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,
			(TSizeX >= 0) ? a_NBT.GetType(TSizeX) : -1,
			(TSizeY >= 0) ? a_NBT.GetType(TSizeY) : -1,
			(TSizeZ >= 0) ? a_NBT.GetType(TSizeZ) : -1
		);
		return false;
	}

	int SizeX = a_NBT.GetShort(TSizeX);
	int SizeY = a_NBT.GetShort(TSizeY);
	int SizeZ = a_NBT.GetShort(TSizeZ);
	if ((SizeX < 1) || (SizeX > 65535) || (SizeY < 1) || (SizeY > cChunkDef::Height) || (SizeZ < 1) || (SizeZ > 65535))
	{
		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);

	a_BlockArea.Clear();
	a_BlockArea.SetSize(SizeX, SizeY, SizeZ, AreMetasPresent ? (cBlockArea::baTypes | cBlockArea::baMetas) : cBlockArea::baTypes);

	int TOffsetX = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetX");
	int TOffsetY = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetY");
	int TOffsetZ = a_NBT.FindChildByName(a_NBT.GetRoot(), "WEOffsetZ");

	if (
		(TOffsetX < 0) || (TOffsetY < 0) || (TOffsetZ < 0) ||
		(a_NBT.GetType(TOffsetX) != TAG_Int) ||
		(a_NBT.GetType(TOffsetY) != TAG_Int) ||
		(a_NBT.GetType(TOffsetZ) != TAG_Int)
	)
	{
		// Not every schematic file has an offset, so we shoudn't give a warn message.
		a_BlockArea.SetWEOffset(0, 0, 0);
	}
	else
	{
		a_BlockArea.SetWEOffset(a_NBT.GetInt(TOffsetX), a_NBT.GetInt(TOffsetY), a_NBT.GetInt(TOffsetZ));
	}

	// Copy the block types and metas:
	size_t NumTypeBytes = a_BlockArea.GetBlockCount();
	if (a_NBT.GetDataLength(TBlockTypes) < NumTypeBytes)
	{
		LOG("BlockTypes truncated in the schematic file (exp %u, got %u bytes). Loading partial.",
			static_cast<unsigned>(NumTypeBytes), static_cast<unsigned>(a_NBT.GetDataLength(TBlockTypes))
		);
		NumTypeBytes = a_NBT.GetDataLength(TBlockTypes);
	}
	memcpy(a_BlockArea.GetBlockTypes(), a_NBT.GetData(TBlockTypes), NumTypeBytes);

	if (AreMetasPresent)
	{
		size_t NumMetaBytes = a_BlockArea.GetBlockCount();
		if (a_NBT.GetDataLength(TBlockMetas) < NumMetaBytes)
		{
			LOG("BlockMetas truncated in the schematic file (exp %u, got %u bytes). Loading partial.",
				static_cast<unsigned>(NumMetaBytes), static_cast<unsigned>(a_NBT.GetDataLength(TBlockMetas))
			);
			NumMetaBytes = a_NBT.GetDataLength(TBlockMetas);
		}
		memcpy(a_BlockArea.GetBlockMetas(), a_NBT.GetData(TBlockMetas), NumMetaBytes);
	}

	return true;
}