1
0

More cFile cleanup; removed old format writing for block entities

git-svn-id: http://mc-server.googlecode.com/svn/trunk@193 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2012-01-30 16:01:45 +00:00
parent 7e743398a9
commit 51dc47bc70
11 changed files with 345 additions and 288 deletions

View File

@ -59,6 +59,7 @@
#include "cSemaphore.h" #include "cSemaphore.h"
#include "cEvent.h" #include "cEvent.h"
#include "cThread.h" #include "cThread.h"
#include "cFile.h"
#include "cMCLogger.h" #include "cMCLogger.h"

View File

@ -77,46 +77,40 @@ void cChestEntity::SetSlot( int a_Slot, cItem & a_Item )
} }
} }
void cChestEntity::WriteToFile(FILE* a_File)
{
fwrite( &m_BlockType, sizeof( ENUM_BLOCK_ID ), 1, a_File );
fwrite( &m_PosX, sizeof( int ), 1, a_File );
fwrite( &m_PosY, sizeof( int ), 1, a_File );
fwrite( &m_PosZ, sizeof( int ), 1, a_File );
unsigned int NumSlots = c_ChestHeight*c_ChestWidth;
fwrite( &NumSlots, sizeof(unsigned int), 1, a_File );
for(unsigned int i = 0; i < NumSlots; i++)
{ #define READ(File, Var) \
cItem* Item = GetSlot( i ); if (File.Read(&Var, sizeof(Var)) != sizeof(Var)) \
if( Item ) { \
{ LOGERROR("ERROR READING cChestEntity %s FROM FILE (line %d)", #Var, __LINE__); \
fwrite( &Item->m_ItemID, sizeof(Item->m_ItemID), 1, a_File ); return false; \
fwrite( &Item->m_ItemCount, sizeof(Item->m_ItemCount), 1, a_File );
fwrite( &Item->m_ItemHealth, sizeof(Item->m_ItemHealth), 1, a_File );
}
} }
}
bool cChestEntity::LoadFromFile(FILE* a_File) bool cChestEntity::LoadFromFile(cFile & f)
{ {
if( fread( &m_PosX, sizeof(int), 1, a_File) != 1 ) { LOGERROR("ERROR READING CHEST FROM FILE"); return false; } READ(f, m_PosX);
if( fread( &m_PosY, sizeof(int), 1, a_File) != 1 ) { LOGERROR("ERROR READING CHEST FROM FILE"); return false; } READ(f, m_PosY);
if( fread( &m_PosZ, sizeof(int), 1, a_File) != 1 ) { LOGERROR("ERROR READING CHEST FROM FILE"); return false; } READ(f, m_PosZ);
unsigned int NumSlots = 0; unsigned int NumSlots = 0;
if( fread( &NumSlots, sizeof(unsigned int), 1, a_File) != 1 ) { LOGERROR("ERROR READING CHEST FROM FILE"); return false; } READ(f, NumSlots);
for(unsigned int i = 0; i < NumSlots; i++) for(unsigned int i = 0; i < NumSlots; i++)
{ {
cItem Item; cItem Item;
if( fread( &Item.m_ItemID, sizeof(Item.m_ItemID), 1, a_File) != 1 ) { LOGERROR("ERROR READING CHEST FROM FILE"); return false; } READ(f, Item.m_ItemID);
if( fread( &Item.m_ItemCount, sizeof(Item.m_ItemCount), 1, a_File) != 1 ) { LOGERROR("ERROR READING CHEST FROM FILE"); return false; } READ(f, Item.m_ItemCount);
if( fread( &Item.m_ItemHealth, sizeof(Item.m_ItemHealth), 1, a_File)!= 1 ) { LOGERROR("ERROR READING CHEST FROM FILE"); return false; } READ(f, Item.m_ItemHealth);
SetSlot( i, Item ); SetSlot( i, Item );
} }
return true; return true;
} }
bool cChestEntity::LoadFromJson( const Json::Value& a_Value ) bool cChestEntity::LoadFromJson( const Json::Value& a_Value )
{ {
m_PosX = a_Value.get("x", 0).asInt(); m_PosX = a_Value.get("x", 0).asInt();

View File

@ -17,7 +17,7 @@ class cNBTData;
class cChestEntity : public cBlockEntity, public cWindowOwner class cChestEntity : public cBlockEntity, public cWindowOwner
{ {
public: public:
cChestEntity(int a_X, int a_Y, int a_Z, cChunk* a_Chunk); cChestEntity(int a_X, int a_Y, int a_Z, cChunk * a_Chunk);
virtual ~cChestEntity(); virtual ~cChestEntity();
virtual void Destroy(); virtual void Destroy();
@ -26,8 +26,7 @@ public:
cItem * GetSlot( int a_Slot ); cItem * GetSlot( int a_Slot );
void SetSlot( int a_Slot, cItem & a_Item ); void SetSlot( int a_Slot, cItem & a_Item );
void WriteToFile(FILE* a_File); bool LoadFromFile(cFile & a_File); // deprecated format
bool LoadFromFile(FILE* a_File);
bool LoadFromJson( const Json::Value& a_Value ); bool LoadFromJson( const Json::Value& a_Value );
void SaveToJson( Json::Value& a_Value ); void SaveToJson( Json::Value& a_Value );

View File

@ -4,8 +4,6 @@
#ifndef _WIN32 #ifndef _WIN32
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <sys/stat.h> // for mkdir
#include <sys/types.h>
#endif #endif
@ -52,6 +50,10 @@ typedef std::list< cClientHandle* > ClientHandleList;
typedef std::list< cBlockEntity* > BlockEntityList; typedef std::list< cBlockEntity* > BlockEntityList;
typedef std::list< cEntity* > EntityList; typedef std::list< cEntity* > EntityList;
struct cChunk::sChunkState struct cChunk::sChunkState
{ {
sChunkState() sChunkState()
@ -78,6 +80,36 @@ struct cChunk::sChunkState
int NumRefs; int NumRefs;
}; };
cChunk::cChunk(int a_X, int a_Y, int a_Z, cWorld* a_World)
: m_pState( new sChunkState )
, m_bCalculateLighting( false )
, m_bCalculateHeightmap( false )
, m_PosX( a_X )
, m_PosY( a_Y )
, m_PosZ( a_Z )
, m_BlockType( m_BlockData ) // Offset the pointers
, m_BlockMeta( m_BlockType + c_NumBlocks )
, m_BlockLight( m_BlockMeta + c_NumBlocks/2 )
, m_BlockSkyLight( m_BlockLight + c_NumBlocks/2 )
, m_BlockTickNum( 0 )
, m_BlockTickX( 0 )
, m_BlockTickY( 0 )
, m_BlockTickZ( 0 )
, m_EntitiesCriticalSection( 0 )
, m_World( a_World )
{
//LOG("cChunk::cChunk(%i, %i, %i)", a_X, a_Y, a_Z);
m_EntitiesCriticalSection = new cCriticalSection();
}
cChunk::~cChunk() cChunk::~cChunk()
{ {
//LOG("~cChunk() %i %i %i", m_PosX, m_PosY, m_PosZ ); //LOG("~cChunk() %i %i %i", m_PosX, m_PosY, m_PosZ );
@ -125,31 +157,13 @@ cChunk::~cChunk()
delete m_pState; delete m_pState;
} }
cChunk::cChunk(int a_X, int a_Y, int a_Z, cWorld* a_World)
: m_pState( new sChunkState )
, m_bCalculateLighting( false )
, m_bCalculateHeightmap( false )
, m_PosX( a_X )
, m_PosY( a_Y )
, m_PosZ( a_Z )
, m_BlockType( m_BlockData ) // Offset the pointers
, m_BlockMeta( m_BlockType + c_NumBlocks )
, m_BlockLight( m_BlockMeta + c_NumBlocks/2 )
, m_BlockSkyLight( m_BlockLight + c_NumBlocks/2 )
, m_BlockTickNum( 0 )
, m_BlockTickX( 0 )
, m_BlockTickY( 0 )
, m_BlockTickZ( 0 )
, m_EntitiesCriticalSection( 0 )
, m_World( a_World )
{
//LOG("cChunk::cChunk(%i, %i, %i)", a_X, a_Y, a_Z);
m_EntitiesCriticalSection = new cCriticalSection();
}
void cChunk::Initialize() void cChunk::Initialize()
{ {
if( !LoadFromDisk() ) if (!LoadFromDisk())
{ {
// Clear memory // Clear memory
memset( m_BlockData, 0x00, c_BlockDataSize ); memset( m_BlockData, 0x00, c_BlockDataSize );
@ -163,9 +177,8 @@ void cChunk::Initialize()
// During generation, some blocks might have been set by using (Fast)SetBlock() causing this list to fill. // During generation, some blocks might have been set by using (Fast)SetBlock() causing this list to fill.
// This chunk has not been sent to anybody yet, so there is no need for separately sending block changes when you can send an entire chunk // This chunk has not been sent to anybody yet, so there is no need for separately sending block changes when you can send an entire chunk
m_pState->BlockListCriticalSection.Lock(); cCSLock Lock(m_pState->BlockListCriticalSection);
m_pState->PendingSendBlocks.clear(); m_pState->PendingSendBlocks.clear();
m_pState->BlockListCriticalSection.Unlock();
} }
else else
{ {
@ -174,14 +187,22 @@ void cChunk::Initialize()
} }
} }
void cChunk::Tick(float a_Dt) void cChunk::Tick(float a_Dt)
{ {
if( m_bCalculateLighting ) if (m_bCalculateLighting)
{
CalculateLighting(); CalculateLighting();
if( m_bCalculateHeightmap ) }
if (m_bCalculateHeightmap)
{
CalculateHeightmap(); CalculateHeightmap();
}
m_pState->BlockListCriticalSection.Lock(); cCSLock Lock(m_pState->BlockListCriticalSection);
unsigned int PendingSendBlocks = m_pState->PendingSendBlocks.size(); unsigned int PendingSendBlocks = m_pState->PendingSendBlocks.size();
if( PendingSendBlocks > 1 ) if( PendingSendBlocks > 1 )
{ {
@ -228,7 +249,7 @@ void cChunk::Tick(float a_Dt)
} }
m_pState->PendingSendBlocks.clear(); m_pState->PendingSendBlocks.clear();
} }
m_pState->BlockListCriticalSection.Unlock(); Lock.Unlock();
while( !m_pState->UnloadQuery.empty() ) while( !m_pState->UnloadQuery.empty() )
{ {
@ -872,179 +893,137 @@ cBlockEntity* cChunk::GetBlockEntity( int a_X, int a_Y, int a_Z )
return 0; return 0;
} }
/// Loads the chunk from the old-format disk file, erases the file afterwards. Returns true if successful
bool cChunk::LoadFromDisk() bool cChunk::LoadFromDisk()
{ {
char SourceFile[128]; char SourceFile[128];
sprintf_s(SourceFile, 128, "world/X%i_Y%i_Z%i.bin", m_PosX, m_PosY, m_PosZ ); sprintf_s(SourceFile, ARRAYCOUNT(SourceFile), "world/X%i_Y%i_Z%i.bin", m_PosX, m_PosY, m_PosZ );
FILE* f = 0; cFile f;
#ifdef _WIN32 if (!f.Open(SourceFile, cFile::fmRead))
if( fopen_s(&f, SourceFile, "rb" ) == 0 ) // no error
#else
if( (f = fopen(SourceFile, "rb" )) != 0 ) // no error
#endif
{ {
if( fread( m_BlockData, sizeof(char)*c_BlockDataSize, 1, f) != 1 ) { LOGERROR("ERROR READING FROM FILE %s", SourceFile); fclose(f); return false; } return false;
}
// Now load Block Entities if (f.Read(m_BlockData, sizeof(m_BlockData)) != sizeof(m_BlockData))
m_pState->BlockListCriticalSection.Lock(); {
ENUM_BLOCK_ID BlockType; LOGERROR("ERROR READING FROM FILE %s", SourceFile);
while( fread( &BlockType, sizeof(ENUM_BLOCK_ID), 1, f) == 1 ) return false;
}
// Now load Block Entities
cCSLock Lock(m_pState->BlockListCriticalSection);
ENUM_BLOCK_ID BlockType;
while (f.Read(&BlockType, sizeof(ENUM_BLOCK_ID)) == sizeof(ENUM_BLOCK_ID))
{
switch (BlockType)
{ {
switch( BlockType )
{
case E_BLOCK_CHEST: case E_BLOCK_CHEST:
{
cChestEntity * ChestEntity = new cChestEntity( 0, 0, 0, this );
if (!ChestEntity->LoadFromFile(f))
{ {
cChestEntity* ChestEntity = new cChestEntity( 0, 0, 0, this ); LOGERROR("ERROR READING CHEST FROM FILE %s", SourceFile );
if( !ChestEntity->LoadFromFile( f ) ) delete ChestEntity;
{ return false;
LOGERROR("ERROR READING CHEST FROM FILE %s", SourceFile );
delete ChestEntity;
fclose(f);
return false;
}
m_pState->BlockEntities.push_back( ChestEntity );
} }
m_pState->BlockEntities.push_back( ChestEntity );
break; break;
}
case E_BLOCK_FURNACE: case E_BLOCK_FURNACE:
{
cFurnaceEntity* FurnaceEntity = new cFurnaceEntity( 0, 0, 0, this );
if (!FurnaceEntity->LoadFromFile(f))
{ {
cFurnaceEntity* FurnaceEntity = new cFurnaceEntity( 0, 0, 0, this ); LOGERROR("ERROR READING FURNACE FROM FILE %s", SourceFile );
if( !FurnaceEntity->LoadFromFile( f ) ) delete FurnaceEntity;
{ return false;
LOGERROR("ERROR READING FURNACE FROM FILE %s", SourceFile );
delete FurnaceEntity;
fclose(f);
return false;
}
m_pState->BlockEntities.push_back( FurnaceEntity );
m_pState->TickBlockEntities.push_back( FurnaceEntity ); // They need tickin'
} }
m_pState->BlockEntities.push_back( FurnaceEntity );
m_pState->TickBlockEntities.push_back( FurnaceEntity ); // They need tickin'
break; break;
}
case E_BLOCK_SIGN_POST: case E_BLOCK_SIGN_POST:
case E_BLOCK_WALLSIGN: case E_BLOCK_WALLSIGN:
{
cSignEntity * SignEntity = new cSignEntity(BlockType, 0, 0, 0, this );
if (!SignEntity->LoadFromFile( f ) )
{ {
cSignEntity* SignEntity = new cSignEntity(BlockType, 0, 0, 0, this ); LOGERROR("ERROR READING SIGN FROM FILE %s", SourceFile );
if( !SignEntity->LoadFromFile( f ) ) delete SignEntity;
{ return false;
LOGERROR("ERROR READING SIGN FROM FILE %s", SourceFile );
delete SignEntity;
fclose(f);
return false;
}
m_pState->BlockEntities.push_back( SignEntity );
} }
m_pState->BlockEntities.push_back( SignEntity );
break; break;
}
default: default:
{
assert(!"Unhandled block entity in file");
break; break;
} }
} }
m_pState->BlockListCriticalSection.Unlock(); }
Lock.Unlock();
f.Close();
fclose(f); // Delete old format file
if (std::remove(SourceFile) != 0)
// Delete old format file {
if( std::remove( SourceFile ) != 0 ) LOGERROR("Could not delete file %s", SourceFile );
LOGERROR("Could not delete file %s", SourceFile );
else
LOGINFO("Successfully deleted olf format file %s", SourceFile );
return true;
} }
else else
{ {
//LOGWARN("COULD NOT OPEN FILE %s\n", SourceFile); LOGINFO("Successfully deleted old format file \"%s\"", SourceFile );
return false;
} }
return true;
} }
bool cChunk::SaveToDisk() bool cChunk::SaveToDisk()
{ {
assert(!"Old save format not supported anymore"); // Remove the call to this function
return true; //no more saving old format! return true; //no more saving old format!
char SourceFile[128];
sprintf_s(SourceFile, 128, "world/X%i_Y%i_Z%i.bin", m_PosX, m_PosY, 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( m_BlockData, sizeof(char)*c_BlockDataSize, 1, f );
m_pState->BlockListCriticalSection.Lock();
// Now write Block Entities
for( std::list<cBlockEntity*>::iterator itr = m_pState->BlockEntities.begin(); itr != m_pState->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;
}
}
m_pState->BlockListCriticalSection.Unlock();
fclose(f);
return true;
}
else
{
LOGERROR("ERROR WRITING TO FILE %s", SourceFile);
return false;
}
} }
void cChunk::Broadcast( const cPacket & a_Packet, cClientHandle* a_Exclude /* = 0 */ ) const void cChunk::Broadcast( const cPacket & a_Packet, cClientHandle* a_Exclude /* = 0 */ ) const
{ {
for( std::list< cClientHandle* >::const_iterator itr = m_pState->LoadedByClient.begin(); itr != m_pState->LoadedByClient.end(); ++itr ) for( std::list< cClientHandle* >::const_iterator itr = m_pState->LoadedByClient.begin(); itr != m_pState->LoadedByClient.end(); ++itr )
{ {
if( *itr == a_Exclude ) continue; if (*itr == a_Exclude)
{
continue;
}
(*itr)->Send( a_Packet ); (*itr)->Send( a_Packet );
} } // for itr - LoadedByClient[]
} }
void cChunk::LoadFromJson( const Json::Value & a_Value ) void cChunk::LoadFromJson( const Json::Value & a_Value )
{ {
m_pState->BlockListCriticalSection.Lock(); cCSLock Lock(m_pState->BlockListCriticalSection);
// Load chests // Load chests
Json::Value AllChests = a_Value.get("Chests", Json::nullValue); Json::Value AllChests = a_Value.get("Chests", Json::nullValue);
if( !AllChests.empty() ) if (!AllChests.empty())
{ {
for( Json::Value::iterator itr = AllChests.begin(); itr != AllChests.end(); ++itr ) for( Json::Value::iterator itr = AllChests.begin(); itr != AllChests.end(); ++itr )
{ {
@ -1092,50 +1071,58 @@ void cChunk::LoadFromJson( const Json::Value & a_Value )
else m_pState->BlockEntities.push_back( SignEntity ); else m_pState->BlockEntities.push_back( SignEntity );
} }
} }
m_pState->BlockListCriticalSection.Unlock();
} }
void cChunk::SaveToJson( Json::Value & a_Value ) void cChunk::SaveToJson( Json::Value & a_Value )
{ {
Json::Value AllChests; Json::Value AllChests;
Json::Value AllFurnaces; Json::Value AllFurnaces;
Json::Value AllSigns; Json::Value AllSigns;
m_pState->BlockListCriticalSection.Lock(); cCSLock Lock(m_pState->BlockListCriticalSection);
for( std::list<cBlockEntity*>::iterator itr = m_pState->BlockEntities.begin(); itr != m_pState->BlockEntities.end(); ++itr) for (std::list<cBlockEntity*>::iterator itr = m_pState->BlockEntities.begin(); itr != m_pState->BlockEntities.end(); ++itr)
{ {
cBlockEntity* BlockEntity = *itr; cBlockEntity* BlockEntity = *itr;
switch( BlockEntity->GetBlockType() ) switch( BlockEntity->GetBlockType() )
{ {
case E_BLOCK_CHEST: case E_BLOCK_CHEST:
{ {
cChestEntity* ChestEntity = reinterpret_cast< cChestEntity* >( BlockEntity ); cChestEntity* ChestEntity = reinterpret_cast< cChestEntity* >( BlockEntity );
Json::Value NewChest; Json::Value NewChest;
ChestEntity->SaveToJson( NewChest ); ChestEntity->SaveToJson( NewChest );
AllChests.append( NewChest ); AllChests.append( NewChest );
break;
} }
break;
case E_BLOCK_FURNACE: case E_BLOCK_FURNACE:
{ {
cFurnaceEntity* FurnaceEntity = reinterpret_cast< cFurnaceEntity* >( BlockEntity ); cFurnaceEntity* FurnaceEntity = reinterpret_cast< cFurnaceEntity* >( BlockEntity );
Json::Value NewFurnace; Json::Value NewFurnace;
FurnaceEntity->SaveToJson( NewFurnace ); FurnaceEntity->SaveToJson( NewFurnace );
AllFurnaces.append( NewFurnace ); AllFurnaces.append( NewFurnace );
break;
} }
break;
case E_BLOCK_SIGN_POST: case E_BLOCK_SIGN_POST:
case E_BLOCK_WALLSIGN: case E_BLOCK_WALLSIGN:
{ {
cSignEntity* SignEntity = reinterpret_cast< cSignEntity* >( BlockEntity ); cSignEntity* SignEntity = reinterpret_cast< cSignEntity* >( BlockEntity );
Json::Value NewSign; Json::Value NewSign;
SignEntity->SaveToJson( NewSign ); SignEntity->SaveToJson( NewSign );
AllSigns.append( NewSign ); AllSigns.append( NewSign );
break;
} }
break;
default: default:
break; {
} assert(!"Unhandled blocktype in BlockEntities list while saving to JSON");
} break;
m_pState->BlockListCriticalSection.Unlock(); }
} // switch (BlockEntity->GetBlockType())
} // for itr - BlockEntities[]
if( !AllChests.empty() ) if( !AllChests.empty() )
a_Value["Chests"] = AllChests; a_Value["Chests"] = AllChests;
@ -1145,29 +1132,47 @@ void cChunk::SaveToJson( Json::Value & a_Value )
a_Value["Signs"] = AllSigns; a_Value["Signs"] = AllSigns;
} }
EntityList & cChunk::GetEntities() EntityList & cChunk::GetEntities()
{ {
return m_pState->Entities; return m_pState->Entities;
} }
const ClientHandleList & cChunk::GetClients() const ClientHandleList & cChunk::GetClients()
{ {
return m_pState->LoadedByClient; return m_pState->LoadedByClient;
} }
void cChunk::AddTickBlockEntity( cFurnaceEntity* a_Entity ) void cChunk::AddTickBlockEntity( cFurnaceEntity* a_Entity )
{ {
m_pState->TickBlockEntities.remove( a_Entity ); m_pState->TickBlockEntities.remove( a_Entity );
m_pState->TickBlockEntities.push_back( a_Entity ); m_pState->TickBlockEntities.push_back( a_Entity );
} }
void cChunk::RemoveTickBlockEntity( cFurnaceEntity* a_Entity ) void cChunk::RemoveTickBlockEntity( cFurnaceEntity* a_Entity )
{ {
m_pState->TickBlockEntities.remove( a_Entity ); m_pState->TickBlockEntities.remove( a_Entity );
} }
void cChunk::PositionToWorldPosition(int a_ChunkX, int a_ChunkY, int a_ChunkZ, int & a_X, int & a_Y, int & a_Z) void cChunk::PositionToWorldPosition(int a_ChunkX, int a_ChunkY, int a_ChunkZ, int & a_X, int & a_Y, int & a_Z)
{ {
a_Y = a_ChunkY; a_Y = a_ChunkY;
@ -1175,32 +1180,50 @@ void cChunk::PositionToWorldPosition(int a_ChunkX, int a_ChunkY, int a_ChunkZ, i
a_Z = m_PosZ * 16 + a_ChunkZ; a_Z = m_PosZ * 16 + a_ChunkZ;
} }
void cChunk::AddReference() void cChunk::AddReference()
{ {
m_pState->ReferenceCriticalSection.Lock(); cCSLock Lock(m_pState->ReferenceCriticalSection);
m_pState->NumRefs++; m_pState->NumRefs++;
m_pState->ReferenceCriticalSection.Unlock();
} }
void cChunk::RemoveReference() void cChunk::RemoveReference()
{ {
m_pState->ReferenceCriticalSection.Lock(); cCSLock Lock(m_pState->ReferenceCriticalSection);
m_pState->NumRefs--; m_pState->NumRefs--;
if( m_pState->NumRefs < 0 ) assert (m_pState->NumRefs >= 0);
if (m_pState->NumRefs < 0)
{ {
LOGWARN("WARNING: cChunk: Tried to remove reference, but the chunk is not referenced!"); LOGWARN("WARNING: cChunk: Tried to remove reference, but the chunk is not referenced!");
} }
m_pState->ReferenceCriticalSection.Unlock();
} }
int cChunk::GetReferenceCount() int cChunk::GetReferenceCount()
{ {
m_pState->ReferenceCriticalSection.Lock(); cCSLock Lock(m_pState->ReferenceCriticalSection);
int Refs = m_pState->NumRefs; int Refs = m_pState->NumRefs;
m_pState->ReferenceCriticalSection.Unlock();
return Refs; return Refs;
} }
#if !C_CHUNK_USE_INLINE #if !C_CHUNK_USE_INLINE
# include "cChunk.inc" # include "cChunk.inc"
#endif #endif

View File

@ -17,10 +17,6 @@
#include <json/json.h> #include <json/json.h>
// TODO: Move this into Globals.h after cFile has been finalized
#include "cFile.h"
#define USE_MEMCPY #define USE_MEMCPY
#define LAYER_SIZE (32) #define LAYER_SIZE (32)

View File

@ -92,6 +92,19 @@ cCSLock::cCSLock(cCriticalSection * a_CS)
cCSLock::cCSLock(cCriticalSection & a_CS)
: m_CS(&a_CS)
#ifdef _DEBUG
, m_IsLocked(false)
#endif
{
Lock();
}
cCSLock::~cCSLock() cCSLock::~cCSLock()
{ {
Unlock(); Unlock();

View File

@ -30,6 +30,7 @@ class cCSLock
public: public:
cCSLock(cCriticalSection * a_CS); cCSLock(cCriticalSection * a_CS);
cCSLock(cCriticalSection & a_CS);
~cCSLock(); ~cCSLock();
// Temporarily unlock or re-lock: // Temporarily unlock or re-lock:

View File

@ -219,67 +219,54 @@ void cFurnaceEntity::ResetCookTimer()
m_CookTime = 0.f; m_CookTime = 0.f;
} }
void cFurnaceEntity::WriteToFile(FILE* a_File)
{
fwrite( &m_BlockType, sizeof( ENUM_BLOCK_ID ), 1, a_File );
fwrite( &m_PosX, sizeof( int ), 1, a_File );
fwrite( &m_PosY, sizeof( int ), 1, a_File );
fwrite( &m_PosZ, sizeof( int ), 1, a_File );
unsigned int NumSlots = 3;
fwrite( &NumSlots, sizeof(unsigned int), 1, a_File );
for(unsigned int i = 0; i < NumSlots; i++)
{ #define READ(File, Var) \
cItem* Item = &m_Items[i]; if (File.Read(&Var, sizeof(Var)) != sizeof(Var)) \
if( Item ) { \
{ LOGERROR("ERROR READING cFurnaceEntity %s FROM FILE (line %d)", #Var, __LINE__); \
fwrite( &Item->m_ItemID, sizeof(Item->m_ItemID), 1, a_File ); return false; \
fwrite( &Item->m_ItemCount, sizeof(Item->m_ItemCount), 1, a_File );
fwrite( &Item->m_ItemHealth, sizeof(Item->m_ItemHealth), 1, a_File );
}
} }
cItem Item;
if( m_CookingItem ) Item = *m_CookingItem;
fwrite( &Item.m_ItemID, sizeof(Item.m_ItemID), 1, a_File );
fwrite( &Item.m_ItemCount, sizeof(Item.m_ItemCount), 1, a_File );
fwrite( &Item.m_ItemHealth, sizeof(Item.m_ItemHealth), 1, a_File );
fwrite( &m_CookTime, sizeof(float), 1, a_File ); bool cFurnaceEntity::LoadFromFile(cFile & f)
fwrite( &m_TimeCooked, sizeof(float), 1, a_File );
fwrite( &m_BurnTime, sizeof(float), 1, a_File );
fwrite( &m_TimeBurned, sizeof(float), 1, a_File );
}
bool cFurnaceEntity::LoadFromFile(FILE* a_File)
{ {
if( fread( &m_PosX, sizeof(int), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, m_PosX);
if( fread( &m_PosY, sizeof(int), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, m_PosY);
if( fread( &m_PosZ, sizeof(int), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, m_PosZ);
unsigned int NumSlots = 0; unsigned int NumSlots = 0;
if( fread( &NumSlots, sizeof(unsigned int), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, NumSlots);
m_Items = new cItem[ NumSlots ]; m_Items = new cItem[ NumSlots ];
for(unsigned int i = 0; i < NumSlots; i++) for(unsigned int i = 0; i < NumSlots; i++)
{ {
cItem & Item = m_Items[ i ]; cItem & Item = m_Items[i];
if( fread( &Item.m_ItemID, sizeof(Item.m_ItemID), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, Item.m_ItemID);
if( fread( &Item.m_ItemCount, sizeof(Item.m_ItemCount), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, Item.m_ItemCount);
if( fread( &Item.m_ItemHealth, sizeof(Item.m_ItemHealth), 1, a_File)!= 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, Item.m_ItemHealth);
}
cItem CookingItem;
READ(f, CookingItem.m_ItemID);
READ(f, CookingItem.m_ItemCount);
READ(f, CookingItem.m_ItemHealth);
if (!CookingItem.IsEmpty())
{
m_CookingItem = new cItem(CookingItem);
} }
cItem Item;
if( fread( &Item.m_ItemID, sizeof(Item.m_ItemID), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; }
if( fread( &Item.m_ItemCount, sizeof(Item.m_ItemCount), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; }
if( fread( &Item.m_ItemHealth, sizeof(Item.m_ItemHealth), 1, a_File)!= 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; }
if( !Item.IsEmpty() ) m_CookingItem = new cItem( Item );
if( fread( &m_CookTime, sizeof(float), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, m_CookTime);
if( fread( &m_TimeCooked, sizeof(float), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, m_TimeCooked);
if( fread( &m_BurnTime, sizeof(float), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, m_BurnTime);
if( fread( &m_TimeBurned, sizeof(float), 1, a_File) != 1 ) { LOGERROR("ERROR READING FURNACE FROM FILE"); return false; } READ(f, m_TimeBurned);
return true; return true;
} }
bool cFurnaceEntity::LoadFromJson( const Json::Value& a_Value ) bool cFurnaceEntity::LoadFromJson( const Json::Value& a_Value )
{ {
m_PosX = a_Value.get("x", 0).asInt(); m_PosX = a_Value.get("x", 0).asInt();

View File

@ -21,11 +21,10 @@ public:
virtual ~cFurnaceEntity(); virtual ~cFurnaceEntity();
virtual void Destroy(); virtual void Destroy();
void WriteToFile(FILE* a_File); bool LoadFromFile(cFile & a_File); // deprecated format
bool LoadFromFile(FILE* a_File);
bool LoadFromJson( const Json::Value& a_Value ); bool LoadFromJson(const Json::Value& a_Value );
void SaveToJson( Json::Value& a_Value ); void SaveToJson (Json::Value& a_Value );
bool Tick( float a_Dt ); bool Tick( float a_Dt );
virtual void UsedBy( cPlayer & a_Player ); virtual void UsedBy( cPlayer & a_Player );

View File

@ -22,16 +22,28 @@ cSignEntity::cSignEntity(ENUM_BLOCK_ID a_BlockType, int a_X, int a_Y, int a_Z, c
{ {
} }
cSignEntity::~cSignEntity() cSignEntity::~cSignEntity()
{ {
} }
// It don't do anything when 'used' // It don't do anything when 'used'
void cSignEntity::UsedBy( cPlayer & a_Player ) void cSignEntity::UsedBy( cPlayer & a_Player )
{ {
(void)a_Player; (void)a_Player;
} }
void cSignEntity::SetLines( const std::string & a_Line1, const std::string & a_Line2, const std::string & a_Line3, const std::string & a_Line4 ) void cSignEntity::SetLines( const std::string & a_Line1, const std::string & a_Line2, const std::string & a_Line3, const std::string & a_Line4 )
{ {
m_Line[0] = a_Line1; m_Line[0] = a_Line1;
@ -40,6 +52,10 @@ void cSignEntity::SetLines( const std::string & a_Line1, const std::string & a_L
m_Line[3] = a_Line4; m_Line[3] = a_Line4;
} }
void cSignEntity::SetLine( int a_Index, std::string a_Line ) void cSignEntity::SetLine( int a_Index, std::string a_Line )
{ {
if( a_Index < 4 && a_Index > -1 ) if( a_Index < 4 && a_Index > -1 )
@ -48,6 +64,10 @@ void cSignEntity::SetLine( int a_Index, std::string a_Line )
} }
} }
std::string cSignEntity::GetLine( int a_Index ) std::string cSignEntity::GetLine( int a_Index )
{ {
if( a_Index < 4 && a_Index > -1 ) if( a_Index < 4 && a_Index > -1 )
@ -57,6 +77,10 @@ std::string cSignEntity::GetLine( int a_Index )
return ""; return "";
} }
void cSignEntity::SendTo( cClientHandle* a_Client ) void cSignEntity::SendTo( cClientHandle* a_Client )
{ {
cPacket_UpdateSign Sign; cPacket_UpdateSign Sign;
@ -68,51 +92,58 @@ void cSignEntity::SendTo( cClientHandle* a_Client )
Sign.m_Line3 = m_Line[2]; Sign.m_Line3 = m_Line[2];
Sign.m_Line4 = m_Line[3]; Sign.m_Line4 = m_Line[3];
if( a_Client ) a_Client->Send( Sign ); if( a_Client )
{
a_Client->Send( Sign );
}
else // broadcast of a_Client == 0 else // broadcast of a_Client == 0
{ {
GetChunk()->Broadcast( Sign ); GetChunk()->Broadcast( Sign );
} }
} }
void cSignEntity::WriteToFile(FILE* a_File)
{
fwrite( &m_BlockType, sizeof( ENUM_BLOCK_ID ), 1, a_File );
fwrite( &m_PosX, sizeof( int ), 1, a_File );
fwrite( &m_PosY, sizeof( int ), 1, a_File );
fwrite( &m_PosZ, sizeof( int ), 1, a_File );
for( int i = 0; i < 4; i++ )
{
short Size = (short)m_Line[i].size();
fwrite( &Size, sizeof(short), 1, a_File ); #define READ(File, Var) \
fwrite( m_Line[i].c_str(), Size * sizeof(char), 1, a_File ); if (File.Read(&Var, sizeof(Var)) != sizeof(Var)) \
{ \
LOGERROR("ERROR READING cSignEntity %s FROM FILE (line %d)", #Var, __LINE__); \
return false; \
} }
}
bool cSignEntity::LoadFromFile(FILE* a_File) bool cSignEntity::LoadFromFile(cFile & f)
{ {
if( fread( &m_PosX, sizeof(int), 1, a_File) != 1 ) { LOGERROR("ERROR READING SIGN FROM FILE"); return false; } READ(f, m_PosX);
if( fread( &m_PosY, sizeof(int), 1, a_File) != 1 ) { LOGERROR("ERROR READING SIGN FROM FILE"); return false; } READ(f, m_PosY);
if( fread( &m_PosZ, sizeof(int), 1, a_File) != 1 ) { LOGERROR("ERROR READING SIGN FROM FILE"); return false; } READ(f, m_PosZ);
for( int i = 0; i < 4; i++ ) for( int i = 0; i < 4; i++ )
{ {
short Size = 0; short Size = 0;
if( fread( &Size, sizeof(short), 1, a_File) != 1 ) { LOGERROR("ERROR READING SIGN FROM FILE"); return false; } READ(f, Size);
if( Size > 0 ) if (Size > 0)
{ {
char* c_Str = new char[Size]; char * c_Str = new char[Size];
if( fread( c_Str, Size * sizeof(char), 1, a_File) != 1 ) { LOGERROR("ERROR READING SIGN FROM FILE"); delete [] c_Str; return false; } if (f.Read(c_Str, Size) != Size )
{
LOGERROR("ERROR READING SIGN FROM FILE");
delete [] c_Str;
return false;
}
m_Line[i].assign( c_Str, Size ); m_Line[i].assign( c_Str, Size );
delete [] c_Str; delete [] c_Str;
} }
LOG("Line %i: %s", i+1, m_Line[i].c_str() );
} }
return true; return true;
} }
bool cSignEntity::LoadFromJson( const Json::Value & a_Value ) bool cSignEntity::LoadFromJson( const Json::Value & a_Value )
{ {
m_PosX = a_Value.get("x", 0).asInt(); m_PosX = a_Value.get("x", 0).asInt();
@ -137,4 +168,8 @@ void cSignEntity::SaveToJson( Json::Value & a_Value )
a_Value["Line2"] = m_Line[1]; a_Value["Line2"] = m_Line[1];
a_Value["Line3"] = m_Line[2]; a_Value["Line3"] = m_Line[2];
a_Value["Line4"] = m_Line[3]; a_Value["Line4"] = m_Line[3];
} }

View File

@ -3,13 +3,19 @@
#include "cBlockEntity.h" #include "cBlockEntity.h"
#include "FileDefine.h" #include "FileDefine.h"
#include <string>
namespace Json namespace Json
{ {
class Value; class Value;
} }
class cWorld; class cWorld;
class cSignEntity : public cBlockEntity class cSignEntity : public cBlockEntity
{ {
@ -17,8 +23,7 @@ public:
cSignEntity(ENUM_BLOCK_ID a_BlockType, int a_X, int a_Y, int a_Z, cChunk* a_Chunk); cSignEntity(ENUM_BLOCK_ID a_BlockType, int a_X, int a_Y, int a_Z, cChunk* a_Chunk);
virtual ~cSignEntity(); virtual ~cSignEntity();
void WriteToFile(FILE* a_File); bool LoadFromFile(cFile & a_File); // deprecated format
bool LoadFromFile(FILE* a_File);
bool LoadFromJson( const Json::Value& a_Value ); bool LoadFromJson( const Json::Value& a_Value );
void SaveToJson( Json::Value& a_Value ); void SaveToJson( Json::Value& a_Value );
@ -32,4 +37,8 @@ public:
virtual void SendTo( cClientHandle* a_Client ); virtual void SendTo( cClientHandle* a_Client );
private: private:
std::string m_Line[4]; std::string m_Line[4];
}; };