summaryrefslogtreecommitdiffstats
path: root/source/cChunkLoader.cpp
diff options
context:
space:
mode:
authorfaketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6>2011-10-03 20:41:19 +0200
committerfaketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6>2011-10-03 20:41:19 +0200
commit386d58b5862d8b76925c6523721594887606e82a (patch)
treeef073e7a843f4b75a4008d4b7383f7cdf08ceee5 /source/cChunkLoader.cpp
parentVisual Studio 2010 solution and project files (diff)
downloadcuberite-386d58b5862d8b76925c6523721594887606e82a.tar
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.gz
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.bz2
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.lz
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.xz
cuberite-386d58b5862d8b76925c6523721594887606e82a.tar.zst
cuberite-386d58b5862d8b76925c6523721594887606e82a.zip
Diffstat (limited to 'source/cChunkLoader.cpp')
-rw-r--r--source/cChunkLoader.cpp364
1 files changed, 364 insertions, 0 deletions
diff --git a/source/cChunkLoader.cpp b/source/cChunkLoader.cpp
new file mode 100644
index 000000000..a5d07818d
--- /dev/null
+++ b/source/cChunkLoader.cpp
@@ -0,0 +1,364 @@
+#if 0 // ignore all contents of this file
+#include "cChunkLoader.h"
+#include "cChunk.h"
+#include "cMCLogger.h"
+#include "BlockID.h"
+#include "cCriticalSection.h"
+#include "cEvent.h"
+#include "cThread.h"
+#include "cSleep.h"
+
+#include "cChestEntity.h"
+#include "cFurnaceEntity.h"
+#include "cSignEntity.h"
+
+#include <iostream>
+#ifndef _WIN32
+#include <cstring>
+#include <cstdlib>
+#include <stdio.h>
+#include <sys/stat.h> // for mkdir
+#include <sys/types.h>
+#else
+#include <Windows.h>
+#endif
+
+#include <list>
+
+struct ChunkData
+{
+ ChunkData()
+ : x( 0 )
+ , z( 0 )
+ , Data( 0 )
+ , LiveChunk( 0 )
+ {}
+ int x, z;
+ unsigned int DataSize;
+ unsigned int ChunkStart;
+ char* Data;
+ cChunk* LiveChunk;
+};
+
+typedef std::list< ChunkData > ChunkDataList;
+struct cChunkLoader::ChunkPack
+{
+ ChunkDataList AllChunks;
+ int x, y, z;
+};
+
+typedef std::list< cChunkLoader::ChunkPack > ChunkPackList;
+struct cChunkLoader::ChunkPacks
+{
+ ChunkPackList AllPacks;
+};
+
+cChunkLoader::cChunkLoader()
+ : m_bStop( false )
+ , m_CriticalSection( new cCriticalSection() )
+ , m_Event( new cEvent() )
+ , m_ChunkPacks( new ChunkPacks )
+{
+ cThread( SaveThread, this );
+}
+
+cChunkLoader::~cChunkLoader()
+{
+ m_bStop = true;
+ m_Event->Wait();
+ delete m_CriticalSection;
+}
+
+void cChunkLoader::SaveThread( void* a_Param )
+{
+ cChunkLoader* self = (cChunkLoader*)a_Param;
+ while( !self->m_bStop )
+ {
+ cSleep::MilliSleep( 1000 ); // Only check for saving once a second
+ }
+ self->m_Event->Set();
+}
+
+cChunk* cChunkLoader::LoadChunk( int a_X, int a_Y, int a_Z )
+{
+ m_CriticalSection->Lock();
+ cChunk* Chunk = 0;
+
+ Chunk = LoadOldFormat( a_X, a_Y, a_Z );
+ if( Chunk ) { Chunk->CalculateHeightmap(); }
+ else
+ {
+ 1; // load new format()
+ }
+
+ m_CriticalSection->Unlock();
+ return Chunk;
+}
+
+bool cChunkLoader::SaveChunk( const cChunk & a_Chunk )
+{
+ m_CriticalSection->Lock();
+ bool Success = SaveOldFormat( a_Chunk );
+ m_CriticalSection->Unlock();
+
+ return Success;
+}
+
+/**************************************************
+ * Old format stuffs
+ **/
+
+cChunk* cChunkLoader::LoadOldFormat( int a_X, int a_Y, int a_Z )
+{
+ char SourceFile[128];
+ sprintf_s(SourceFile, 128, "world/X%i_Y%i_Z%i.bin", a_X, a_Y, a_Z );
+
+ FILE* f = 0;
+ #ifdef _WIN32
+ if( fopen_s(&f, SourceFile, "rb" ) == 0 ) // no error
+ #else
+ if( (f = fopen(SourceFile, "rb" )) != 0 ) // no error
+ #endif
+ {
+ cChunk* Chunk = new cChunk( a_X, a_Y, a_Z );
+ if( fread( Chunk->m_BlockData, sizeof(char)*cChunk::c_BlockDataSize, 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; }
+
+ // Now load Block Entities
+ ENUM_BLOCK_ID BlockType;
+ while( fread( &BlockType, sizeof(ENUM_BLOCK_ID), 1, f) == 1 )
+ {
+ switch( BlockType )
+ {
+ case E_BLOCK_CHEST:
+ {
+ cChestEntity* ChestEntity = new cChestEntity( 0, 0, 0 );
+ if( !ChestEntity->LoadFromFile( f ) )
+ {
+ LOGERROR("ERROR READING CHEST FROM FILE %s", SourceFile );
+ delete ChestEntity;
+ fclose(f);
+ return false;
+ }
+ Chunk->m_BlockEntities.push_back( ChestEntity );
+ }
+ break;
+ case E_BLOCK_FURNACE:
+ {
+ cFurnaceEntity* FurnaceEntity = new cFurnaceEntity( 0, 0, 0 );
+ if( !FurnaceEntity->LoadFromFile( f ) )
+ {
+ LOGERROR("ERROR READING FURNACE FROM FILE %s", SourceFile );
+ delete FurnaceEntity;
+ fclose(f);
+ return false;
+ }
+ Chunk->m_BlockEntities.push_back( FurnaceEntity );
+ Chunk->m_TickBlockEntities.push_back( FurnaceEntity ); // They need tickin'
+ }
+ break;
+ case E_BLOCK_SIGN_POST:
+ case E_BLOCK_WALLSIGN:
+ {
+ cSignEntity* SignEntity = new cSignEntity(BlockType, 0, 0, 0 );
+ if( !SignEntity->LoadFromFile( f ) )
+ {
+ LOGERROR("ERROR READING SIGN FROM FILE %s", SourceFile );
+ delete SignEntity;
+ fclose(f);
+ return false;
+ }
+ Chunk->m_BlockEntities.push_back( SignEntity );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ fclose(f);
+ return Chunk;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+bool cChunkLoader::SaveOldFormat( const cChunk & a_Chunk )
+{
+ char SourceFile[128];
+ sprintf_s(SourceFile, 128, "world/X%i_Y%i_Z%i.bin", a_Chunk.m_PosX, a_Chunk.m_PosY, a_Chunk.m_PosZ );
+
+ #ifdef _WIN32
+ {
+ SECURITY_ATTRIBUTES Attrib;
+ Attrib.nLength = sizeof(SECURITY_ATTRIBUTES);
+ Attrib.lpSecurityDescriptor = NULL;
+ Attrib.bInheritHandle = false;
+ ::CreateDirectory("world", &Attrib);
+ }
+ #else
+ {
+ mkdir("world", S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ #endif
+
+ FILE* f = 0;
+#ifdef _WIN32
+ if( fopen_s(&f, SourceFile, "wb" ) == 0 ) // no error
+ #else
+ if( (f = fopen(SourceFile, "wb" )) != 0 ) // no error
+ #endif
+ {
+ fwrite( a_Chunk.m_BlockData, sizeof(char)*cChunk::c_BlockDataSize, 1, f );
+
+ // Now write Block Entities
+ for( std::list<cBlockEntity*>::const_iterator itr = a_Chunk.m_BlockEntities.begin(); itr != a_Chunk.m_BlockEntities.end(); ++itr)
+ {
+ cBlockEntity* BlockEntity = *itr;
+ switch( BlockEntity->GetBlockType() )
+ {
+ case E_BLOCK_CHEST:
+ {
+ cChestEntity* ChestEntity = reinterpret_cast< cChestEntity* >( BlockEntity );
+ ChestEntity->WriteToFile( f );
+ }
+ break;
+ case E_BLOCK_FURNACE:
+ {
+ cFurnaceEntity* FurnaceEntity = reinterpret_cast< cFurnaceEntity* >( BlockEntity );
+ FurnaceEntity->WriteToFile( f );
+ }
+ break;
+ case E_BLOCK_SIGN_POST:
+ case E_BLOCK_WALLSIGN:
+ {
+ cSignEntity* SignEntity = reinterpret_cast< cSignEntity* >( BlockEntity );
+ SignEntity->WriteToFile( f );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ fclose(f);
+ return true;
+ }
+ else
+ {
+ LOGERROR("ERROR WRITING TO FILE %s", SourceFile);
+ return false;
+ }
+}
+
+
+/******************************************
+ * New format
+ **/
+
+cChunk* cChunkLoader::LoadFormat1( int a_X, int a_Y, int a_Z )
+{
+ int PakX = (int)(floorf((float)a_X / 16.f));
+ int PakY = (int)(floorf((float)a_Y / 16.f));
+ int PakZ = (int)(floorf((float)a_Z / 16.f));
+
+ ChunkPack * Pack = 0;
+ ChunkPackList & PackList = m_ChunkPacks->AllPacks;
+ for( ChunkPackList::iterator itr = PackList.begin(); itr != PackList.end(); ++itr )
+ {
+ if( itr->x == PakX && itr->y == PakY && itr->z == PakZ )
+ {
+ Pack = &(*itr);
+ break;
+ }
+ }
+
+
+ if( !Pack ) // The pack was not in memory, so try to load it from disk
+ {
+ Pack = LoadPak1( PakX, PakY, PakZ ); // Load .pak file from disk
+ if( Pack )
+ {
+ PackList.push_back( *Pack ); // Add it to the loaded list
+ }
+ }
+
+ if( Pack ) // Allright, the pack is in memory
+ {
+ ChunkData * Data = 0;
+ ChunkDataList & ChunkList = Pack->AllChunks;
+ for( ChunkDataList::iterator itr = ChunkList.begin(); itr != ChunkList.end(); ++itr )
+ {
+ if( itr->x == a_X && itr->z == a_Z )
+ {
+ Data = &(*itr);
+ break;
+ }
+ }
+
+ if( !Data ) // Sorry, chunk does not exist (yet)
+ return 0;
+
+ if( Data->LiveChunk ) // This chunk is already loaded and decoded (this should actually never happen)
+ return Data->LiveChunk;
+
+ // Decompress chunk, and return brand new chunk
+
+ // doing it...
+
+ return 0; // actually return the chunk
+ }
+
+ return 0; // .pak file didn't exist
+}
+
+cChunkLoader::ChunkPack* cChunkLoader::LoadPak1( int PakX, int PakY, int PakZ )
+{
+ char SourceFile[128];
+ sprintf_s(SourceFile, 128, "world/X%i_Y%i_Z%i.pak", PakX, PakY, PakZ );
+
+ FILE* f = 0;
+ #ifdef _WIN32
+ if( fopen_s(&f, SourceFile, "rb" ) == 0 ) // no error
+ #else
+ if( (f = fopen(SourceFile, "rb" )) != 0 ) // no error
+ #endif
+ {
+ cChunkLoader::ChunkPack * Pack = new cChunkLoader::ChunkPack;
+ Pack->x = PakX;
+ Pack->y = PakY;
+ Pack->z = PakZ;
+
+ short Version = 0;
+ if( fread( &Version, sizeof( short ), 1, f ) != 1 ) { LOGERROR("Error reading file %s", SourceFile ); return 0; }
+ if( Version != 1 ) { LOGERROR("Wrong pak version! %s", SourceFile ); return 0; }
+ short NumChunks = 0;
+ if( fread( &NumChunks, sizeof( short ), 1, f ) != 1 ) { LOGERROR("Error reading file %s", SourceFile ); return 0; }
+
+ // Load all the headers
+ for( short i = 0; i < NumChunks; ++i )
+ {
+ ChunkData Data;
+ if( fread( &Data.x, sizeof( int ), 1, f ) != 1 ) { LOGERROR("Error reading file %s", SourceFile ); return 0; }
+ if( fread( &Data.z, sizeof( int ), 1, f ) != 1 ) { LOGERROR("Error reading file %s", SourceFile ); return 0; }
+ if( fread( &Data.DataSize, sizeof( unsigned int ), 1, f ) != 1 ) { LOGERROR("Error reading file %s", SourceFile ); return 0; }
+ if( fread( &Data.ChunkStart, sizeof( unsigned int ), 1, f ) != 1 ) { LOGERROR("Error reading file %s", SourceFile ); return 0; }
+ Pack->AllChunks.push_back( Data );
+ }
+
+ // Load all compressed chunk data in the order the headers were loaded
+ ChunkDataList::iterator itr = Pack->AllChunks.begin();
+ for( short i = 0; i < NumChunks; ++i )
+ {
+ itr->Data = new char[ itr->DataSize ];
+ if( fread( itr->Data, sizeof( char ) * itr->DataSize, 1, f ) != 1 ) { LOGERROR("Error reading file %s", SourceFile ); return 0; }
+ ++itr;
+ }
+
+ // And we're done :)
+ return Pack;
+ }
+ return 0;
+}
+#endif \ No newline at end of file