summaryrefslogtreecommitdiffstats
path: root/src/WorldStorage
diff options
context:
space:
mode:
Diffstat (limited to 'src/WorldStorage')
-rw-r--r--src/WorldStorage/FastNBT.h4
-rw-r--r--src/WorldStorage/NBTChunkSerializer.cpp1
-rw-r--r--src/WorldStorage/WSSAnvil.cpp498
-rw-r--r--src/WorldStorage/WSSAnvil.h31
-rw-r--r--src/WorldStorage/WSSCompact.cpp6
-rw-r--r--src/WorldStorage/WorldStorage.cpp28
-rw-r--r--src/WorldStorage/WorldStorage.h12
7 files changed, 322 insertions, 258 deletions
diff --git a/src/WorldStorage/FastNBT.h b/src/WorldStorage/FastNBT.h
index 4ef72e379..ebf99103f 100644
--- a/src/WorldStorage/FastNBT.h
+++ b/src/WorldStorage/FastNBT.h
@@ -76,7 +76,9 @@ public:
cFastNBTTag(eTagType a_Type, int a_Parent) :
m_Type(a_Type),
+ m_NameStart(0),
m_NameLength(0),
+ m_DataStart(0),
m_DataLength(0),
m_Parent(a_Parent),
m_PrevSibling(-1),
@@ -88,7 +90,9 @@ public:
cFastNBTTag(eTagType a_Type, int a_Parent, int a_PrevSibling) :
m_Type(a_Type),
+ m_NameStart(0),
m_NameLength(0),
+ m_DataStart(0),
m_DataLength(0),
m_Parent(a_Parent),
m_PrevSibling(a_PrevSibling),
diff --git a/src/WorldStorage/NBTChunkSerializer.cpp b/src/WorldStorage/NBTChunkSerializer.cpp
index e435a1b1f..68e541eba 100644
--- a/src/WorldStorage/NBTChunkSerializer.cpp
+++ b/src/WorldStorage/NBTChunkSerializer.cpp
@@ -615,7 +615,6 @@ void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
{
m_Writer.BeginCompound("");
AddBasicEntity(a_Projectile, a_Projectile->GetMCAClassName());
- Vector3d Pos = a_Projectile->GetPosition();
m_Writer.AddByte("inGround", a_Projectile->IsInGround() ? 1 : 0);
switch (a_Projectile->GetProjectileKind())
diff --git a/src/WorldStorage/WSSAnvil.cpp b/src/WorldStorage/WSSAnvil.cpp
index a9c9ae4b5..4d2f92173 100644
--- a/src/WorldStorage/WSSAnvil.cpp
+++ b/src/WorldStorage/WSSAnvil.cpp
@@ -66,8 +66,17 @@ Since only the header is actually in the memory, this number can be high, but st
*/
#define MAX_MCA_FILES 32
-/// The maximum size of an inflated chunk; raw chunk data is 192 KiB, allow 64 KiB more of entities
-#define CHUNK_INFLATE_MAX 256 KiB
+#define LOAD_FAILED(CHX, CHZ) \
+ { \
+ const int RegionX = FAST_FLOOR_DIV(CHX, 32); \
+ const int RegionZ = FAST_FLOOR_DIV(CHZ, 32); \
+ LOGERROR("%s (%d): Loading chunk [%d, %d] from file r.%d.%d.mca failed. " \
+ "The server will now abort in order to avoid further data loss. " \
+ "Please add the reported file and this message to the issue report.", \
+ __FUNCTION__, __LINE__, CHX, CHZ, RegionX, RegionZ \
+ ); \
+ *((volatile int *)0) = 0; /* Crash intentionally */ \
+ }
@@ -248,29 +257,22 @@ cWSSAnvil::cMCAFile * cWSSAnvil::LoadMCAFile(const cChunkCoords & a_Chunk)
bool cWSSAnvil::LoadChunkFromData(const cChunkCoords & a_Chunk, const AString & a_Data)
{
- // Decompress the data:
- char Uncompressed[CHUNK_INFLATE_MAX];
- z_stream strm;
- strm.zalloc = (alloc_func)NULL;
- strm.zfree = (free_func)NULL;
- strm.opaque = NULL;
- inflateInit(&strm);
- strm.next_out = (Bytef *)Uncompressed;
- strm.avail_out = sizeof(Uncompressed);
- strm.next_in = (Bytef *)a_Data.data();
- strm.avail_in = (uInt)a_Data.size();
- int res = inflate(&strm, Z_FINISH);
- inflateEnd(&strm);
- if (res != Z_STREAM_END)
+ // Uncompress the data:
+ AString Uncompressed;
+ int res = InflateString(a_Data.data(), a_Data.size(), Uncompressed);
+ if (res != Z_OK)
{
+ LOGWARNING("Uncompressing chunk [%d, %d] failed: %d", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, res);
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
// Parse the NBT data:
- cParsedNBT NBT(Uncompressed, strm.total_out);
+ cParsedNBT NBT(Uncompressed.data(), Uncompressed.size());
if (!NBT.IsValid())
{
// NBT Parsing failed
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
@@ -317,11 +319,13 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
int Level = a_NBT.FindChildByName(0, "Level");
if (Level < 0)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
int Sections = a_NBT.FindChildByName(Level, "Sections");
if ((Sections < 0) || (a_NBT.GetType(Sections) != TAG_List) || (a_NBT.GetChildrenType(Sections) != TAG_Compound))
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
for (int Child = a_NBT.GetFirstChild(Sections); Child >= 0; Child = a_NBT.GetNextSibling(Child))
@@ -396,7 +400,7 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
} // for y
//*/
- m_World->QueueSetChunkData(cSetChunkDataPtr(new cSetChunkData(
+ cSetChunkDataPtr SetChunkData(new cSetChunkData(
a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ,
BlockTypes, MetaData,
IsLightValid ? BlockLight : NULL,
@@ -404,7 +408,8 @@ bool cWSSAnvil::LoadChunkFromNBT(const cChunkCoords & a_Chunk, const cParsedNBT
NULL, Biomes,
Entities, BlockEntities,
false
- )));
+ ));
+ m_World->QueueSetChunkData(SetChunkData);
return true;
}
@@ -581,64 +586,28 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
{
continue;
}
- int sID = a_NBT.FindChildByName(Child, "id");
- if (sID < 0)
+
+ // Get the BlockEntity's position
+ int x, y, z;
+ if (!GetBlockEntityNBTPos(a_NBT, Child, x, y, z))
{
+ LOGWARNING("Bad block entity, missing the coords. Will be ignored.");
continue;
}
- if (strncmp(a_NBT.GetData(sID), "Beacon", a_NBT.GetDataLength(sID)) == 0)
- {
- LoadBeaconFromNBT(a_BlockEntities, a_NBT, Child);
- }
- else if (strncmp(a_NBT.GetData(sID), "Chest", a_NBT.GetDataLength(sID)) == 0)
- {
- LoadChestFromNBT(a_BlockEntities, a_NBT, Child, E_BLOCK_CHEST);
- }
- else if (strncmp(a_NBT.GetData(sID), "Control", a_NBT.GetDataLength(sID)) == 0)
- {
- LoadCommandBlockFromNBT(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), "FlowerPot", a_NBT.GetDataLength(sID)) == 0)
- {
- LoadFlowerPotFromNBT(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), "Skull", a_NBT.GetDataLength(sID)) == 0)
- {
- LoadMobHeadFromNBT(a_BlockEntities, a_NBT, Child);
- }
- else if (strncmp(a_NBT.GetData(sID), "Trap", a_NBT.GetDataLength(sID)) == 0)
+ int RelX = x, RelY = y, RelZ = z, ChunkX, ChunkZ;
+ cChunkDef::AbsoluteToRelative(RelX, RelY, RelZ, ChunkX, ChunkZ);
+
+ // Load the proper BlockEntity type based on the block type:
+ BLOCKTYPE BlockType = cChunkDef::GetBlock(a_BlockTypes, RelX, RelY, RelZ);
+ NIBBLETYPE BlockMeta = cChunkDef::GetNibble(a_BlockMetas, RelX, RelY, RelZ);
+ std::auto_ptr<cBlockEntity> be(LoadBlockEntityFromNBT(a_NBT, Child, x, y, z, BlockType, BlockMeta));
+ if (be.get() == NULL)
{
- LoadDispenserFromNBT(a_BlockEntities, a_NBT, Child);
- }
- else if (strncmp(a_NBT.GetData(sID), "TrappedChest", a_NBT.GetDataLength(sID)) == 0)
- {
- LoadChestFromNBT(a_BlockEntities, a_NBT, Child, E_BLOCK_TRAPPED_CHEST);
+ continue;
}
- // TODO: Other block entities
+
+ // Add the BlockEntity to the loaded data:
+ a_BlockEntities.push_back(be.release());
} // for Child - tag children
}
@@ -646,6 +615,52 @@ void cWSSAnvil::LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntities, con
+cBlockEntity * cWSSAnvil::LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a_Tag, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
+{
+ // Load the specific BlockEntity type:
+ switch (a_BlockType)
+ {
+ // Specific entity loaders:
+ case E_BLOCK_BEACON: return LoadBeaconFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_CHEST);
+ case E_BLOCK_COMMAND_BLOCK: return LoadCommandBlockFromNBT(a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_DISPENSER: return LoadDispenserFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_DROPPER: return LoadDropperFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_FLOWER_POT: return LoadFlowerPotFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_FURNACE: return LoadFurnaceFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FURNACE, a_BlockMeta);
+ case E_BLOCK_HEAD: return LoadMobHeadFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_HOPPER: return LoadHopperFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_JUKEBOX: return LoadJukeboxFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_LIT_FURNACE: return LoadFurnaceFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_LIT_FURNACE, a_BlockMeta);
+ case E_BLOCK_NOTE_BLOCK: return LoadNoteBlockFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ);
+ case E_BLOCK_SIGN_POST: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_SIGN_POST);
+ case E_BLOCK_TRAPPED_CHEST: return LoadChestFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_TRAPPED_CHEST);
+ case E_BLOCK_WALLSIGN: return LoadSignFromNBT (a_NBT, a_Tag, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WALLSIGN);
+
+ // Blocktypes that have block entities but don't load their contents from disk:
+ case E_BLOCK_ENDER_CHEST: return NULL;
+ }
+
+ // All the other blocktypes should have no entities assigned to them. Report an error:
+ // Get the "id" tag:
+ int TagID = a_NBT.FindChildByName(a_Tag, "id");
+ AString TypeName("<unknown>");
+ if (TagID >= 0)
+ {
+ TypeName.assign(a_NBT.GetData(TagID), (size_t)a_NBT.GetDataLength(TagID));
+ }
+ LOGINFO("WorldLoader(%s): Block entity mismatch: block type %s (%d), type \"%s\", at {%d, %d, %d}; the entity will be lost.",
+ m_World->GetName().c_str(),
+ ItemTypeToString(a_BlockType).c_str(), a_BlockType, TypeName.c_str(),
+ a_BlockX, a_BlockY, a_BlockZ
+ );
+ return NULL;
+}
+
+
+
+
+
bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx)
{
int Type = a_NBT.FindChildByName(a_TagIdx, "id");
@@ -656,7 +671,6 @@ bool cWSSAnvil::LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_
a_Item.m_ItemType = a_NBT.GetShort(Type);
if (a_Item.m_ItemType < 0)
{
- LOGD("Encountered an item with negative type (%d). Replacing with an empty item.", a_NBT.GetShort(Type));
a_Item.Empty();
return true;
}
@@ -754,16 +768,46 @@ void cWSSAnvil::LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a
-void cWSSAnvil::LoadBeaconFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+bool cWSSAnvil::CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const char * a_ExpectedType)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the given tag is a compound:
+ if (a_NBT.GetType(a_TagIdx) != TAG_Compound)
{
- return;
+ return false;
}
- std::auto_ptr<cBeaconEntity> Beacon(new cBeaconEntity(x, y, z, m_World));
+ // Get the "id" tag:
+ int TagID = a_NBT.FindChildByName(a_TagIdx, "id");
+ if (TagID < 0)
+ {
+ return false;
+ }
+
+ // Compare the value:
+ if (strncmp(a_NBT.GetData(TagID), a_ExpectedType, (size_t)a_NBT.GetDataLength(TagID)) == 0)
+ {
+ return true;
+ }
+ LOGWARNING("Block entity type mismatch: exp \"%s\", got \"%s\".",
+ a_ExpectedType,
+ AString(a_NBT.GetData(TagID), (size_t)a_NBT.GetDataLength(TagID)).c_str()
+ );
+ return false;
+}
+
+
+
+
+
+cBlockEntity * cWSSAnvil::LoadBeaconFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Beacon"))
+ {
+ return NULL;
+ }
+
+ std::auto_ptr<cBeaconEntity> Beacon(new cBeaconEntity(a_BlockX, a_BlockY, a_BlockZ, m_World));
int CurrentLine = a_NBT.FindChildByName(a_TagIdx, "Levels");
if (CurrentLine >= 0)
@@ -790,88 +834,128 @@ void cWSSAnvil::LoadBeaconFromNBT(cBlockEntityList & a_BlockEntities, const cPar
LoadItemGridFromNBT(Beacon->GetContents(), a_NBT, Items);
}
- a_BlockEntities.push_back(Beacon.release());
+ return Beacon.release();
}
-void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_ChestType)
+cBlockEntity * cWSSAnvil::LoadChestFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_ChestBlockType)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ // TODO: Does vanilla use "TrappedChest" or not? MCWiki says no, but previous code says yes
+ // Ref.: http://minecraft.gamepedia.com/Trapped_Chest
+ // https://github.com/mc-server/MCServer/blob/d0551e2e0a98a28f31a88d489d17b408e4a7d38d/src/WorldStorage/WSSAnvil.cpp#L637
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Chest") && !CheckBlockEntityType(a_NBT, a_TagIdx, "TrappedChest"))
{
- return;
+ return NULL;
}
+
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
+ return NULL; // Make it an empty chest - the chunk loader will provide an empty cChestEntity for this
}
- std::auto_ptr<cChestEntity> Chest(new cChestEntity(x, y, z, m_World, a_ChestType));
+ std::auto_ptr<cChestEntity> Chest(new cChestEntity(a_BlockX, a_BlockY, a_BlockZ, m_World, a_ChestBlockType));
LoadItemGridFromNBT(Chest->GetContents(), a_NBT, Items);
- a_BlockEntities.push_back(Chest.release());
+ return Chest.release();
}
-void cWSSAnvil::LoadDispenserFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+cBlockEntity * cWSSAnvil::LoadCommandBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Control"))
{
- return;
+ return NULL;
+ }
+
+ std::auto_ptr<cCommandBlockEntity> CmdBlock(new cCommandBlockEntity(a_BlockX, a_BlockY, a_BlockZ, m_World));
+
+ int currentLine = a_NBT.FindChildByName(a_TagIdx, "Command");
+ if (currentLine >= 0)
+ {
+ CmdBlock->SetCommand(a_NBT.GetString(currentLine));
+ }
+
+ currentLine = a_NBT.FindChildByName(a_TagIdx, "SuccessCount");
+ if (currentLine >= 0)
+ {
+ CmdBlock->SetResult(a_NBT.GetInt(currentLine));
+ }
+
+ currentLine = a_NBT.FindChildByName(a_TagIdx, "LastOutput");
+ if (currentLine >= 0)
+ {
+ CmdBlock->SetLastOutput(a_NBT.GetString(currentLine));
+ }
+
+ // TODO 2014-01-18 xdot: Figure out what TrackOutput is and parse it.
+
+ return CmdBlock.release();
+}
+
+
+
+
+
+cBlockEntity * cWSSAnvil::LoadDispenserFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
+{
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Trap"))
+ {
+ return NULL;
}
+
int Items = a_NBT.FindChildByName(a_TagIdx, "Items");
if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List))
{
- return; // Make it an empty dispenser - the chunk loader will provide an empty cDispenserEntity for this
+ return NULL; // Make it an empty dispenser - the chunk loader will provide an empty cDispenserEntity for this
}
- std::auto_ptr<cDispenserEntity> Dispenser(new cDispenserEntity(x, y, z, m_World));
+ std::auto_ptr<cDispenserEntity> Dispenser(new cDispenserEntity(a_BlockX, a_BlockY, a_BlockZ, m_World));
LoadItemGridFromNBT(Dispenser->GetContents(), a_NBT, Items);
- a_BlockEntities.push_back(Dispenser.release());
+ return Dispenser.release();
}
-void cWSSAnvil::LoadDropperFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+cBlockEntity * cWSSAnvil::LoadDropperFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Dropper"))
{
- return;
+ return NULL;
}
+
int Items = a_NBT.FindChildByName(a_TagIdx, "Items");
if ((Items < 0) || (a_NBT.GetType(Items) != TAG_List))
{
- return; // Make it an empty dropper - the chunk loader will provide an empty cDropperEntity for this
+ return NULL; // Make it an empty dropper - the chunk loader will provide an empty cDropperEntity for this
}
- std::auto_ptr<cDropperEntity> Dropper(new cDropperEntity(x, y, z, m_World));
+ std::auto_ptr<cDropperEntity> Dropper(new cDropperEntity(a_BlockX, a_BlockY, a_BlockZ, m_World));
LoadItemGridFromNBT(Dropper->GetContents(), a_NBT, Items);
- a_BlockEntities.push_back(Dropper.release());
+ return Dropper.release();
}
-void cWSSAnvil::LoadFlowerPotFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+cBlockEntity * cWSSAnvil::LoadFlowerPotFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "FlowerPot"))
{
- return;
+ return NULL;
}
- std::auto_ptr<cFlowerPotEntity> FlowerPot(new cFlowerPotEntity(x, y, z, m_World));
+
+ std::auto_ptr<cFlowerPotEntity> FlowerPot(new cFlowerPotEntity(a_BlockX, a_BlockY, a_BlockZ, m_World));
short ItemType = 0, ItemData = 0;
int currentLine = a_NBT.FindChildByName(a_TagIdx, "Item");
@@ -887,37 +971,28 @@ void cWSSAnvil::LoadFlowerPotFromNBT(cBlockEntityList & a_BlockEntities, const c
}
FlowerPot->SetItem(cItem(ItemType, 1, ItemData));
- a_BlockEntities.push_back(FlowerPot.release());
+ return FlowerPot.release();
}
-void cWSSAnvil::LoadFurnaceFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE * a_BlockTypes, NIBBLETYPE * a_BlockMetas)
+cBlockEntity * cWSSAnvil::LoadFurnaceFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Furnace"))
{
- return;
+ return NULL;
}
+
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
+ return NULL; // 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));
+ std::auto_ptr<cFurnaceEntity> Furnace(new cFurnaceEntity(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta, m_World));
// Load slots:
for (int Child = a_NBT.GetFirstChild(Items); Child != -1; Child = a_NBT.GetNextSibling(Child))
@@ -954,184 +1029,147 @@ void cWSSAnvil::LoadFurnaceFromNBT(cBlockEntityList & a_BlockEntities, const cPa
// Restart cooking:
Furnace->ContinueCooking();
- a_BlockEntities.push_back(Furnace.release());
+ return Furnace.release();
}
-void cWSSAnvil::LoadHopperFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+cBlockEntity * cWSSAnvil::LoadHopperFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Hopper"))
{
- return;
+ return NULL;
}
+
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
+ return NULL; // 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));
+ std::auto_ptr<cHopperEntity> Hopper(new cHopperEntity(a_BlockX, a_BlockY, a_BlockZ, m_World));
LoadItemGridFromNBT(Hopper->GetContents(), a_NBT, Items);
- a_BlockEntities.push_back(Hopper.release());
+ return Hopper.release();
}
-void cWSSAnvil::LoadJukeboxFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+cBlockEntity * cWSSAnvil::LoadJukeboxFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "RecordPlayer"))
{
- return;
+ return NULL;
}
- std::auto_ptr<cJukeboxEntity> Jukebox(new cJukeboxEntity(x, y, z, m_World));
+
+ std::auto_ptr<cJukeboxEntity> Jukebox(new cJukeboxEntity(a_BlockX, a_BlockY, a_BlockZ, 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());
+ return Jukebox.release();
}
-void cWSSAnvil::LoadNoteFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+cBlockEntity * cWSSAnvil::LoadMobHeadFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Skull"))
{
- 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::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;
+ return NULL;
}
- 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));
- }
+ std::auto_ptr<cMobHeadEntity> MobHead(new cMobHeadEntity(a_BlockX, a_BlockY, a_BlockZ, m_World));
- currentLine = a_NBT.FindChildByName(a_TagIdx, "Text2");
+ int currentLine = a_NBT.FindChildByName(a_TagIdx, "SkullType");
if (currentLine >= 0)
{
- Sign->SetLine(1, a_NBT.GetString(currentLine));
+ MobHead->SetType(static_cast<eMobHeadType>(a_NBT.GetByte(currentLine)));
}
- currentLine = a_NBT.FindChildByName(a_TagIdx, "Text3");
+ currentLine = a_NBT.FindChildByName(a_TagIdx, "Rot");
if (currentLine >= 0)
{
- Sign->SetLine(2, a_NBT.GetString(currentLine));
+ MobHead->SetRotation(static_cast<eMobHeadRotation>(a_NBT.GetByte(currentLine)));
}
- currentLine = a_NBT.FindChildByName(a_TagIdx, "Text4");
+ currentLine = a_NBT.FindChildByName(a_TagIdx, "ExtraType");
if (currentLine >= 0)
{
- Sign->SetLine(3, a_NBT.GetString(currentLine));
+ MobHead->SetOwner(a_NBT.GetString(currentLine));
}
- a_BlockEntities.push_back(Sign.release());
+ return MobHead.release();
}
-void cWSSAnvil::LoadMobHeadFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+cBlockEntity * cWSSAnvil::LoadNoteBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Music"))
{
- return;
- }
- std::auto_ptr<cMobHeadEntity> MobHead(new cMobHeadEntity(x, y, z, m_World));
-
- int currentLine = a_NBT.FindChildByName(a_TagIdx, "SkullType");
- if (currentLine >= 0)
- {
- MobHead->SetType(static_cast<eMobHeadType>(a_NBT.GetByte(currentLine)));
- }
-
- currentLine = a_NBT.FindChildByName(a_TagIdx, "Rot");
- if (currentLine >= 0)
- {
- MobHead->SetRotation(static_cast<eMobHeadRotation>(a_NBT.GetByte(currentLine)));
+ return NULL;
}
- currentLine = a_NBT.FindChildByName(a_TagIdx, "ExtraType");
- if (currentLine >= 0)
+ std::auto_ptr<cNoteEntity> NoteBlock(new cNoteEntity(a_BlockX, a_BlockY, a_BlockZ, m_World));
+ int note = a_NBT.FindChildByName(a_TagIdx, "note");
+ if (note >= 0)
{
- MobHead->SetOwner(a_NBT.GetString(currentLine));
+ NoteBlock->SetPitch(a_NBT.GetByte(note));
}
-
- a_BlockEntities.push_back(MobHead.release());
+ return NoteBlock.release();
}
-void cWSSAnvil::LoadCommandBlockFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx)
+cBlockEntity * cWSSAnvil::LoadSignFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType)
{
- ASSERT(a_NBT.GetType(a_TagIdx) == TAG_Compound);
- int x, y, z;
- if (!GetBlockEntityNBTPos(a_NBT, a_TagIdx, x, y, z))
+ // Check if the data has a proper type:
+ if (!CheckBlockEntityType(a_NBT, a_TagIdx, "Sign"))
{
- return;
+ return NULL;
}
- std::auto_ptr<cCommandBlockEntity> CmdBlock(new cCommandBlockEntity(x, y, z, m_World));
- int currentLine = a_NBT.FindChildByName(a_TagIdx, "Command");
+ std::auto_ptr<cSignEntity> Sign(new cSignEntity(a_BlockType, a_BlockX, a_BlockY, a_BlockZ, m_World));
+
+ int currentLine = a_NBT.FindChildByName(a_TagIdx, "Text1");
if (currentLine >= 0)
{
- CmdBlock->SetCommand(a_NBT.GetString(currentLine));
+ Sign->SetLine(0, a_NBT.GetString(currentLine));
}
- currentLine = a_NBT.FindChildByName(a_TagIdx, "SuccessCount");
+ currentLine = a_NBT.FindChildByName(a_TagIdx, "Text2");
if (currentLine >= 0)
{
- CmdBlock->SetResult(a_NBT.GetInt(currentLine));
+ Sign->SetLine(1, a_NBT.GetString(currentLine));
}
- currentLine = a_NBT.FindChildByName(a_TagIdx, "LastOutput");
+ currentLine = a_NBT.FindChildByName(a_TagIdx, "Text3");
if (currentLine >= 0)
{
- CmdBlock->SetLastOutput(a_NBT.GetString(currentLine));
+ Sign->SetLine(2, a_NBT.GetString(currentLine));
}
- // TODO 2014-01-18 xdot: Figure out what TrackOutput is and parse it.
+ currentLine = a_NBT.FindChildByName(a_TagIdx, "Text4");
+ if (currentLine >= 0)
+ {
+ Sign->SetLine(3, a_NBT.GetString(currentLine));
+ }
- a_BlockEntities.push_back(CmdBlock.release());
+ return Sign.release();
}
@@ -2777,30 +2815,42 @@ bool cWSSAnvil::cMCAFile::GetChunkData(const cChunkCoords & a_Chunk, AString & a
}
unsigned ChunkLocation = ntohl(m_Header[LocalX + 32 * LocalZ]);
unsigned ChunkOffset = ChunkLocation >> 8;
+ if (ChunkOffset <= 2)
+ {
+ return false;
+ }
m_File.Seek((int)ChunkOffset * 4096);
int ChunkSize = 0;
if (m_File.Read(&ChunkSize, 4) != 4)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
ChunkSize = ntohl((u_long)ChunkSize);
char CompressionType = 0;
if (m_File.Read(&CompressionType, 1) != 1)
{
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
if (CompressionType != 2)
{
// Chunk is in an unknown compression
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
ChunkSize--;
// HACK: This depends on the internal knowledge that AString's data() function returns the internal buffer directly
a_Data.assign(ChunkSize, '\0');
- return (m_File.Read((void *)a_Data.data(), ChunkSize) == ChunkSize);
+ if (m_File.Read((void *)a_Data.data(), ChunkSize) == ChunkSize)
+ {
+ return true;
+ }
+ LOAD_FAILED(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
+ return false;
}
@@ -2855,7 +2905,13 @@ bool cWSSAnvil::cMCAFile::SetChunkData(const cChunkCoords & a_Chunk, const AStri
// Store the header:
ChunkSize = ((u_long)a_Data.size() + MCA_CHUNK_HEADER_LENGTH + 4095) / 4096; // Round data size *up* to nearest 4KB sector, make it a sector number
- ASSERT(ChunkSize < 256);
+ if (ChunkSize > 255)
+ {
+ LOGWARNING("Cannot save chunk [%d, %d], the data is too large (%u KiB, maximum is 1024 KiB). Remove some entities and retry.",
+ a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, (unsigned)(ChunkSize * 4)
+ );
+ return false;
+ }
m_Header[LocalX + 32 * LocalZ] = htonl((ChunkSector << 8) | ChunkSize);
if (m_File.Seek(0) < 0)
{
diff --git a/src/WorldStorage/WSSAnvil.h b/src/WorldStorage/WSSAnvil.h
index 8ddf72115..a1f9b293b 100644
--- a/src/WorldStorage/WSSAnvil.h
+++ b/src/WorldStorage/WSSAnvil.h
@@ -125,6 +125,10 @@ protected:
/// Loads the chunk's BlockEntities from NBT data (a_Tag is the Level\\TileEntities list tag; may be -1)
void LoadBlockEntitiesFromNBT(cBlockEntityList & a_BlockEntitites, const cParsedNBT & a_NBT, int a_Tag, BLOCKTYPE * a_BlockTypes, NIBBLETYPE * a_BlockMetas);
+ /** Loads the data for a block entity from the specified NBT tag.
+ Returns the loaded block entity, or NULL upon failure. */
+ cBlockEntity * LoadBlockEntityFromNBT(const cParsedNBT & a_NBT, int a_Tag, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
+
/// Loads a cItem contents from the specified NBT tag; returns true if successful. Doesn't load the Slot tag
bool LoadItemFromNBT(cItem & a_Item, const cParsedNBT & a_NBT, int a_TagIdx);
@@ -134,18 +138,21 @@ protected:
*/
void LoadItemGridFromNBT(cItemGrid & a_ItemGrid, const cParsedNBT & a_NBT, int a_ItemsTagIdx, int s_SlotOffset = 0);
- void LoadBeaconFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadChestFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE a_ChestType);
- void LoadDispenserFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadDropperFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadFlowerPotFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadFurnaceFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx, BLOCKTYPE * a_BlockTypes, NIBBLETYPE * a_BlockMetas);
- void LoadHopperFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadJukeboxFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadNoteFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadSignFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadMobHeadFromNBT (cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
- void LoadCommandBlockFromNBT(cBlockEntityList & a_BlockEntities, const cParsedNBT & a_NBT, int a_TagIdx);
+ /** Returns true iff the "id" child tag inside the specified tag equals the specified expected type. */
+ bool CheckBlockEntityType(const cParsedNBT & a_NBT, int a_TagIdx, const char * a_ExpectedType);
+
+ cBlockEntity * LoadBeaconFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
+ cBlockEntity * LoadChestFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_ChestBlockType);
+ cBlockEntity * LoadCommandBlockFromNBT(const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
+ cBlockEntity * LoadDispenserFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
+ cBlockEntity * LoadDropperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
+ cBlockEntity * LoadFlowerPotFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
+ cBlockEntity * LoadFurnaceFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
+ cBlockEntity * LoadHopperFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
+ cBlockEntity * LoadJukeboxFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
+ cBlockEntity * LoadMobHeadFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
+ cBlockEntity * LoadNoteBlockFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ);
+ cBlockEntity * LoadSignFromNBT (const cParsedNBT & a_NBT, int a_TagIdx, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_SignBlockType);
void LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_EntityTagIdx, const char * a_IDTag, size_t a_IDTagLength);
diff --git a/src/WorldStorage/WSSCompact.cpp b/src/WorldStorage/WSSCompact.cpp
index 58f9e3cab..6760186b2 100644
--- a/src/WorldStorage/WSSCompact.cpp
+++ b/src/WorldStorage/WSSCompact.cpp
@@ -980,7 +980,7 @@ bool cWSSCompact::cPAKFile::SaveChunkToData(const cChunkCoords & a_Chunk, cWorld
if (!a_World->GetChunkData(a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ, Serializer))
{
// Chunk not valid
- LOG("cWSSCompact: Trying to save chunk [%d, %d, %d] that has no data, ignoring request.", a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ);
+ LOG("cWSSCompact: Trying to save chunk [%d, %d] that has no data, ignoring request.", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
@@ -999,7 +999,7 @@ bool cWSSCompact::cPAKFile::SaveChunkToData(const cChunkCoords & a_Chunk, cWorld
int errorcode = CompressString(Data.data(), Data.size(), CompressedData, m_CompressionFactor);
if (errorcode != Z_OK)
{
- LOGERROR("Error %i compressing data for chunk [%d, %d, %d]", errorcode, a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ);
+ LOGERROR("Error %i compressing data for chunk [%d, %d]", errorcode, a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
@@ -1010,7 +1010,7 @@ bool cWSSCompact::cPAKFile::SaveChunkToData(const cChunkCoords & a_Chunk, cWorld
sChunkHeader * Header = new sChunkHeader;
if (Header == NULL)
{
- LOGWARNING("Cannot create a new chunk header to save chunk [%d, %d, %d]", a_Chunk.m_ChunkX, a_Chunk.m_ChunkY, a_Chunk.m_ChunkZ);
+ LOGWARNING("Cannot create a new chunk header to save chunk [%d, %d]", a_Chunk.m_ChunkX, a_Chunk.m_ChunkZ);
return false;
}
Header->m_CompressedSize = (int)CompressedData.size();
diff --git a/src/WorldStorage/WorldStorage.cpp b/src/WorldStorage/WorldStorage.cpp
index 6e0d36eed..c35bbbad0 100644
--- a/src/WorldStorage/WorldStorage.cpp
+++ b/src/WorldStorage/WorldStorage.cpp
@@ -141,9 +141,9 @@ size_t cWorldStorage::GetSaveQueueLength(void)
-void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate)
+void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkZ, bool a_Generate)
{
- m_LoadQueue.EnqueueItem(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, a_Generate));
+ m_LoadQueue.EnqueueItem(sChunkLoad(a_ChunkX, a_ChunkZ, a_Generate));
m_Event.Set();
}
@@ -151,9 +151,9 @@ void cWorldStorage::QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, boo
-void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkZ)
{
- m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkY, a_ChunkZ));
+ m_SaveQueue.EnqueueItemIfNotPresent(cChunkCoords(a_ChunkX, a_ChunkZ));
m_Event.Set();
}
@@ -161,9 +161,9 @@ void cWorldStorage::QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
-void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+void cWorldStorage::UnqueueLoad(int a_ChunkX, int a_ChunkZ)
{
- m_LoadQueue.Remove(sChunkLoad(a_ChunkX, a_ChunkY, a_ChunkZ, true));
+ m_LoadQueue.Remove(sChunkLoad(a_ChunkX, a_ChunkZ, true));
}
@@ -242,19 +242,19 @@ void cWorldStorage::Execute(void)
bool cWorldStorage::LoadOneChunk(void)
{
- sChunkLoad ToLoad(0, 0, 0, false);
+ sChunkLoad ToLoad(0, 0, false);
bool ShouldLoad = m_LoadQueue.TryDequeueItem(ToLoad);
- if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ))
+ if (ShouldLoad && !LoadChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ))
{
if (ToLoad.m_Generate)
{
// The chunk couldn't be loaded, generate it:
- m_World->GetGenerator().QueueGenerateChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ);
+ m_World->GetGenerator().QueueGenerateChunk(ToLoad.m_ChunkX, ToLoad.m_ChunkZ, false);
}
else
{
// TODO: Notify the world that the load has failed:
- // m_World->ChunkLoadFailed(ToLoad.m_ChunkX, ToLoad.m_ChunkY, ToLoad.m_ChunkZ);
+ // m_World->ChunkLoadFailed(ToLoad.m_ChunkX, ToLoad.m_ChunkZ);
}
}
return ShouldLoad;
@@ -266,7 +266,7 @@ bool cWorldStorage::LoadOneChunk(void)
bool cWorldStorage::SaveOneChunk(void)
{
- cChunkCoords ToSave(0, 0, 0);
+ cChunkCoords ToSave(0, 0);
bool ShouldSave = m_SaveQueue.TryDequeueItem(ToSave);
if (ShouldSave && m_World->IsChunkValid(ToSave.m_ChunkX, ToSave.m_ChunkZ))
{
@@ -283,7 +283,7 @@ bool cWorldStorage::SaveOneChunk(void)
-bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
+bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkZ)
{
if (m_World->IsChunkValid(a_ChunkX, a_ChunkZ))
{
@@ -291,7 +291,7 @@ bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
return true;
}
- cChunkCoords Coords(a_ChunkX, a_ChunkY, a_ChunkZ);
+ cChunkCoords Coords(a_ChunkX, a_ChunkZ);
// First try the schema that is used for saving
if (m_SaveSchema->LoadChunk(Coords))
@@ -309,7 +309,7 @@ bool cWorldStorage::LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
}
// Notify the chunk owner that the chunk failed to load (sets cChunk::m_HasLoadFailed to true):
- m_World->ChunkLoadFailed(a_ChunkX, a_ChunkY, a_ChunkZ);
+ m_World->ChunkLoadFailed(a_ChunkX, a_ChunkZ);
return false;
}
diff --git a/src/WorldStorage/WorldStorage.h b/src/WorldStorage/WorldStorage.h
index 148dc97d0..21f5ca25d 100644
--- a/src/WorldStorage/WorldStorage.h
+++ b/src/WorldStorage/WorldStorage.h
@@ -64,13 +64,13 @@ public:
cWorldStorage(void);
~cWorldStorage();
- void QueueLoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate); // Queues the chunk for loading; if not loaded, the chunk will be generated if a_Generate is true
- void QueueSaveChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void QueueLoadChunk(int a_ChunkX, int a_ChunkZ, bool a_Generate); // Queues the chunk for loading; if not loaded, the chunk will be generated if a_Generate is true
+ void QueueSaveChunk(int a_ChunkX, int a_ChunkZ);
/// Loads the chunk specified; returns true on success, false on failure
- bool LoadChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ bool LoadChunk(int a_ChunkX, int a_ChunkZ);
- void UnqueueLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
+ void UnqueueLoad(int a_ChunkX, int a_ChunkZ);
void UnqueueSave(const cChunkCoords & a_Chunk);
bool Start(cWorld * a_World, const AString & a_StorageSchemaName, int a_StorageCompressionFactor); // Hide the cIsThread's Start() method, we need to provide args
@@ -87,17 +87,15 @@ protected:
struct sChunkLoad
{
int m_ChunkX;
- int m_ChunkY;
int m_ChunkZ;
bool m_Generate; // If true, the chunk will be generated if it cannot be loaded
- sChunkLoad(int a_ChunkX, int a_ChunkY, int a_ChunkZ, bool a_Generate) : m_ChunkX(a_ChunkX), m_ChunkY(a_ChunkY), m_ChunkZ(a_ChunkZ), m_Generate(a_Generate) {}
+ sChunkLoad(int a_ChunkX, int a_ChunkZ, bool a_Generate) : m_ChunkX(a_ChunkX), m_ChunkZ(a_ChunkZ), m_Generate(a_Generate) {}
bool operator ==(const sChunkLoad other) const
{
return (
(this->m_ChunkX == other.m_ChunkX) &&
- (this->m_ChunkY == other.m_ChunkY) &&
(this->m_ChunkZ == other.m_ChunkZ)
);
}