From 578560d2132188279e4b0930212edd915bc90008 Mon Sep 17 00:00:00 2001 From: "madmaxoft@gmail.com" Date: Mon, 1 Apr 2013 20:56:25 +0000 Subject: Proper fix for FS #347. Also unification of ticking block entities. git-svn-id: http://mc-server.googlecode.com/svn/trunk@1348 0a769ca7-a7f5-676a-18bf-c427514a06d6 --- source/BlockEntity.h | 15 +++++++++------ source/Chunk.cpp | 35 +++++++++-------------------------- source/Chunk.h | 2 +- source/DispenserEntity.cpp | 31 ------------------------------- source/DispenserEntity.h | 16 ++++++---------- source/FurnaceEntity.cpp | 46 +--------------------------------------------- source/FurnaceEntity.h | 18 +++++++----------- source/World.cpp | 22 +++++++++++----------- 8 files changed, 44 insertions(+), 141 deletions(-) diff --git a/source/BlockEntity.h b/source/BlockEntity.h index b7d1fe6c4..d62f8aa5e 100644 --- a/source/BlockEntity.h +++ b/source/BlockEntity.h @@ -43,18 +43,18 @@ protected: {} public: virtual ~cBlockEntity() {}; - virtual void Destroy() {}; + virtual void Destroy(void) {}; // Position, in absolute block coordinates: - int GetPosX() { return m_PosX; } - int GetPosY() { return m_PosY; } - int GetPosZ() { return m_PosZ; } + int GetPosX(void) const { return m_PosX; } + int GetPosY(void) const { return m_PosY; } + int GetPosZ(void) const { return m_PosZ; } - ENUM_BLOCK_ID GetBlockType() { return m_BlockType; } + ENUM_BLOCK_ID GetBlockType(void) const { return m_BlockType; } cWorld * GetWorld(void) const {return m_World; } - virtual void SaveToJson (Json::Value & a_Value ) = 0; + virtual void SaveToJson (Json::Value & a_Value) = 0; virtual void UsedBy( cPlayer * a_Player ) = 0; @@ -62,6 +62,9 @@ public: To send to all eligible clients, use cWorld::BroadcastBlockEntity() */ virtual void SendTo(cClientHandle & a_Client) = 0; + + /// Ticks the entity; returns true if the chunk should be marked as dirty as a result of this ticking. By default does nothing. + virtual bool Tick(float a_Dt) { return false; } protected: int m_PosX; // Position in absolute block coordinates diff --git a/source/Chunk.cpp b/source/Chunk.cpp index 9121dd112..ad534f634 100644 --- a/source/Chunk.cpp +++ b/source/Chunk.cpp @@ -296,14 +296,8 @@ void cChunk::SetAllData( CalculateHeightmap(); } - // Initialize incoming entities: - for (cEntityList::iterator itr = a_Entities.begin(), end = a_Entities.end(); itr != end; ++itr) - { - (*itr)->Initialize(m_World); - } // for itr - a_Entities[] - // Append entities to current entity list: - m_Entities.splice(m_Entities.end(), a_Entities); + m_Entities.insert(m_Entities.end(), a_Entities.begin(), a_Entities.end()); // Clear the block entities present - either the loader / saver has better, or we'll create empty ones: for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr) @@ -456,24 +450,13 @@ void cChunk::Tick(float a_Dt, MTRand & a_TickRandom) TickBlocks(a_TickRandom); - // Tick block entities (furnaces) + // Tick all block entities in this chunk: for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr) { - if ((*itr)->GetBlockType() == E_BLOCK_FURNACE) - { - m_IsDirty = ((cFurnaceEntity *)(*itr))->Tick( a_Dt ) | m_IsDirty; - } + m_IsDirty = (*itr)->Tick(a_Dt) | m_IsDirty; } - - // Tick block entities (dispensers) - for (cBlockEntityList::iterator itr = m_BlockEntities.begin(); itr != m_BlockEntities.end(); ++itr) - { - if ((*itr)->GetBlockType() == E_BLOCK_DISPENSER) - { - m_IsDirty = ((cDispenserEntity *)(*itr))->Tick( a_Dt ) | m_IsDirty; - } - } - ApplyWeatherToTop(a_TickRandom); + + ApplyWeatherToTop(); } @@ -570,10 +553,10 @@ void cChunk::TickBlocks(MTRand & a_TickRandom) -void cChunk::ApplyWeatherToTop(MTRand & a_TickRandom) +void cChunk::ApplyWeatherToTop() { if ( - (a_TickRandom.randInt(100) != 0) || + (m_World->GetTickRandomNumber(100) != 0) || ( (m_World->GetWeather() != eWeather_Rain) && (m_World->GetWeather() != eWeather_ThunderStorm) @@ -584,8 +567,8 @@ void cChunk::ApplyWeatherToTop(MTRand & a_TickRandom) return; } - int X = a_TickRandom.randInt(15); - int Z = a_TickRandom.randInt(15); + int X = m_World->GetTickRandomNumber(15); + int Z = m_World->GetTickRandomNumber(15); switch (GetBiomeAt(X, Z)) { case biTaiga: diff --git a/source/Chunk.h b/source/Chunk.h index d7b7fbba6..a15a19466 100644 --- a/source/Chunk.h +++ b/source/Chunk.h @@ -355,7 +355,7 @@ private: void TickBlocks (MTRand & a_TickRandom); /// Adds snow to the top of snowy biomes and hydrates farmland / fills cauldrons in rainy biomes - void ApplyWeatherToTop(MTRand & a_TickRandom); + void ApplyWeatherToTop(void); /// Grows sugarcane by the specified number of blocks, but no more than 3 blocks high (used by both bonemeal and ticking) void GrowSugarcane (int a_RelX, int a_RelY, int a_RelZ, int a_NumBlocks); diff --git a/source/DispenserEntity.cpp b/source/DispenserEntity.cpp index 3ace4a1cf..5b0af8e42 100644 --- a/source/DispenserEntity.cpp +++ b/source/DispenserEntity.cpp @@ -261,37 +261,6 @@ void cDispenserEntity::SetSlot(int a_Slot, const cItem & a_Item) -#define READ(File, Var) \ - if (File.Read(&Var, sizeof(Var)) != sizeof(Var)) \ - { \ - LOGERROR("ERROR READING cDispenserEntity %s FROM FILE (line %d)", #Var, __LINE__); \ - return false; \ - } - -bool cDispenserEntity::LoadFromFile(cFile & f) -{ - READ(f, m_PosX); - READ(f, m_PosY); - READ(f, m_PosZ); - - unsigned int NumSlots = 0; - READ(f, NumSlots); - m_Items = new cItem[ NumSlots ]; - for(unsigned int i = 0; i < NumSlots; i++) - { - cItem & Item = m_Items[i]; - READ(f, Item.m_ItemType); - READ(f, Item.m_ItemCount); - READ(f, Item.m_ItemDamage); - } - - return true; -} - - - - - bool cDispenserEntity::LoadFromJson( const Json::Value& a_Value ) { m_PosX = a_Value.get("x", 0).asInt(); diff --git a/source/DispenserEntity.h b/source/DispenserEntity.h index 9e69878b3..9d27c59c4 100644 --- a/source/DispenserEntity.h +++ b/source/DispenserEntity.h @@ -30,17 +30,13 @@ public: virtual ~cDispenserEntity(); virtual void Destroy(); - bool LoadFromFile(cFile & a_File); // deprecated format - - bool LoadFromJson(const Json::Value& a_Value ); - virtual void SaveToJson(Json::Value& a_Value ) override; - - virtual void SendTo(cClientHandle & a_Client) override; + bool LoadFromJson(const Json::Value & a_Value); - // Returns true if there's any change, forcing the chunk to go dirty. - bool Tick( float a_Dt ); - - virtual void UsedBy( cPlayer * a_Player ) override; + // cBlockEntity overrides: + virtual void SaveToJson(Json::Value & a_Value) override; + virtual void SendTo(cClientHandle & a_Client) override; + virtual bool Tick(float a_Dt) override; + virtual void UsedBy(cPlayer * a_Player) override; const cItem * GetSlot(int i) const { return &(m_Items[i]); } diff --git a/source/FurnaceEntity.cpp b/source/FurnaceEntity.cpp index d464749d8..f6727c555 100644 --- a/source/FurnaceEntity.cpp +++ b/source/FurnaceEntity.cpp @@ -280,51 +280,7 @@ void cFurnaceEntity::SetSlot(int a_Slot, const cItem & a_Item) -#define READ(File, Var) \ - if (File.Read(&Var, sizeof(Var)) != sizeof(Var)) \ - { \ - LOGERROR("ERROR READING cFurnaceEntity %s FROM FILE (line %d)", #Var, __LINE__); \ - return false; \ - } - -bool cFurnaceEntity::LoadFromFile(cFile & f) -{ - READ(f, m_PosX); - READ(f, m_PosY); - READ(f, m_PosZ); - - unsigned int NumSlots = 0; - READ(f, NumSlots); - m_Items = new cItem[ NumSlots ]; - for(unsigned int i = 0; i < NumSlots; i++) - { - cItem & Item = m_Items[i]; - READ(f, Item.m_ItemType); - READ(f, Item.m_ItemCount); - READ(f, Item.m_ItemDamage); - } - cItem CookingItem; - READ(f, CookingItem.m_ItemType); - READ(f, CookingItem.m_ItemCount); - READ(f, CookingItem.m_ItemDamage); - if (!CookingItem.IsEmpty()) - { - m_CookingItem = new cItem(CookingItem); - } - - READ(f, m_CookTime); - READ(f, m_TimeCooked); - READ(f, m_BurnTime); - READ(f, m_TimeBurned); - - 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_PosY = a_Value.get("y", 0).asInt(); diff --git a/source/FurnaceEntity.h b/source/FurnaceEntity.h index bcdc8d837..8373116d4 100644 --- a/source/FurnaceEntity.h +++ b/source/FurnaceEntity.h @@ -32,19 +32,15 @@ public: static const char * GetClassStatic() { return "cFurnaceEntity"; } - bool LoadFromFile(cFile & a_File); // deprecated format - - bool LoadFromJson(const Json::Value& a_Value ); - virtual void SaveToJson(Json::Value& a_Value ) override; - - virtual void SendTo(cClientHandle & a_Client) override; + bool LoadFromJson(const Json::Value & a_Value); - // Returns true if there's any change, forcing the chunk to go dirty. - bool Tick( float a_Dt ); - - virtual void UsedBy( cPlayer * a_Player ) override; + // cBlockEntity overrides: + virtual void SaveToJson(Json::Value & a_Value) override; + virtual void SendTo(cClientHandle & a_Client) override; + virtual bool Tick(float a_Dt) override; + virtual void UsedBy(cPlayer * a_Player) override; - bool StartCooking(); + bool StartCooking(void); /// Restarts cooking. Used after the furnace is loaded from storage to set up the internal variables so that cooking continues, if it was active. Returns true if cooking. bool ContinueCooking(void); diff --git a/source/World.cpp b/source/World.cpp index a573653d7..bef797e06 100644 --- a/source/World.cpp +++ b/source/World.cpp @@ -1599,18 +1599,18 @@ void cWorld::SetChunkData( m_Generator.GenerateBiomes(a_ChunkX, a_ChunkZ, BiomeMap); } + m_ChunkMap->SetChunkData( + a_ChunkX, a_ChunkY, a_ChunkZ, + a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, + a_HeightMap, *Biomes, + a_Entities, a_BlockEntities, + a_MarkDirty + ); + + // Initialize the entities (outside the m_ChunkMap's CS, to fix FS #347): + for (cEntityList::iterator itr = a_Entities.begin(), end = a_Entities.end(); itr != end; ++itr) { - // _X: 2013_04_01: Hotfix for FS #347 - deadlock between the anvil loader thread and the tick thread - // By locking the entities here, we break one of the 3 conditions needed for the deadlock - cCSLock Lock(m_CSEntities); - - m_ChunkMap->SetChunkData( - a_ChunkX, a_ChunkY, a_ChunkZ, - a_BlockTypes, a_BlockMeta, a_BlockLight, a_BlockSkyLight, - a_HeightMap, *Biomes, - a_Entities, a_BlockEntities, - a_MarkDirty - ); + (*itr)->Initialize(this); } // If a client is requesting this chunk, send it to them: -- cgit v1.2.3