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()); }
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 }
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 }
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); } }
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()); }
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; }
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[] }
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; }
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? }
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()); }
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()); }
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()); }
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[] }
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()); }
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()); }
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; } }
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; }
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 }
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; }
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; }
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; }
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; }