diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/cBlockToPickup.cpp | 2 | ||||
-rw-r--r-- | source/cClientHandle.cpp | 127 | ||||
-rw-r--r-- | source/cFireSimulator.cpp | 124 | ||||
-rw-r--r-- | source/cFireSimulator.h | 31 | ||||
-rw-r--r-- | source/cItem.cpp | 2 | ||||
-rw-r--r-- | source/cItem.h | 53 | ||||
-rw-r--r-- | source/cPlayer.cpp | 10 | ||||
-rw-r--r-- | source/cPlayer.h | 2 | ||||
-rw-r--r-- | source/cWorld.cpp | 17 | ||||
-rw-r--r-- | source/cWorld.h | 2 |
10 files changed, 280 insertions, 90 deletions
diff --git a/source/cBlockToPickup.cpp b/source/cBlockToPickup.cpp index 531c9601e..0caca7d1c 100644 --- a/source/cBlockToPickup.cpp +++ b/source/cBlockToPickup.cpp @@ -20,6 +20,8 @@ ENUM_ITEM_ID cBlockToPickup::ToPickup( unsigned char a_BlockID, ENUM_ITEM_ID a_U return E_ITEM_EMPTY;
case E_BLOCK_GRASS:
return E_ITEM_DIRT;
+ case E_BLOCK_FIRE:
+ return E_ITEM_EMPTY;
case E_BLOCK_GLASS:
return E_ITEM_EMPTY;
case E_BLOCK_DIRT:
diff --git a/source/cClientHandle.cpp b/source/cClientHandle.cpp index d65c47e8e..8c49411fe 100644 --- a/source/cClientHandle.cpp +++ b/source/cClientHandle.cpp @@ -587,8 +587,12 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) else
{
cWorld* World = m_Player->GetWorld();
+
+
char OldBlock = World->GetBlock(PacketData->m_PosX, PacketData->m_PosY, PacketData->m_PosZ);
char MetaData = World->GetBlockMeta(PacketData->m_PosX, PacketData->m_PosY, PacketData->m_PosZ);
+
+
bool bBroken = (PacketData->m_Status == 0x02) || g_BlockOneHitDig[(int)OldBlock] || ( (PacketData->m_Status == 0x00) && (m_Player->GetGameMode() == 1) );
if(bBroken == false) bBroken = (m_Player->GetInventory().GetEquippedItem().m_ItemID == E_ITEM_SHEARS && OldBlock == E_BLOCK_LEAVES);
@@ -616,6 +620,20 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) }
if(!cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_BLOCK_DIG, 2, PacketData, m_Player, &PickupItem ) )
{
+ int pX = PacketData->m_PosX, pY = PacketData->m_PosY, pZ = PacketData->m_PosZ;
+
+ AddDirection(pX, (char &) pY, pZ, PacketData->m_Direction);
+
+ char PossibleBlock = World->GetBlock(pX, pY, pZ);
+
+ if(PossibleBlock == E_BLOCK_FIRE)
+ {
+ PacketData->m_PosX = pX;
+ PacketData->m_PosY = pY;
+ PacketData->m_PosZ = pZ;
+ bBroken = true;
+ }
+
if( bBroken ) // Block broken
{
if( World->DigBlock( PacketData->m_PosX, PacketData->m_PosY, PacketData->m_PosZ, PickupItem ) )
@@ -653,78 +671,8 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) World->SetBlock(PacketData->m_PosX, PacketData->m_PosY + 1, PacketData->m_PosZ, E_BLOCK_AIR, 0);
}
}
-
- int helditem = m_Player->GetInventory().GetEquippedItem().m_ItemID;
- bool itemhasdur = false;
- switch(helditem)
- {
- case 256 : itemhasdur = true; break;
- case 257 : itemhasdur = true; break;
- case 258 : itemhasdur = true; break;
- case 267 : itemhasdur = true; break;
- case 268 : itemhasdur = true; break;
- case 269 : itemhasdur = true; break;
- case 270 : itemhasdur = true; break;
- case 271 : itemhasdur = true; break;
- case 272 : itemhasdur = true; break;
- case 273 : itemhasdur = true; break;
- case 274 : itemhasdur = true; break;
- case 275 : itemhasdur = true; break;
- case 276 : itemhasdur = true; break;
- case 277 : itemhasdur = true; break;
- case 278 : itemhasdur = true; break;
- case 279 : itemhasdur = true; break;
- case 283 : itemhasdur = true; break;
- case 284 : itemhasdur = true; break;
- case 285 : itemhasdur = true; break;
- case 286 : itemhasdur = true; break;
- case 290 : itemhasdur = true; break;
- case 291 : itemhasdur = true; break;
- case 292 : itemhasdur = true; break;
- case 293 : itemhasdur = true; break;
- case 294 : itemhasdur = true; break;
- case 359 : itemhasdur = true; break;
- }
- if (itemhasdur)
- {
- int maxhelditemdur = 1563;
- switch(helditem)
- {
- case 256 : maxhelditemdur = 251; break;
- case 257 : maxhelditemdur = 251; break;
- case 258 : maxhelditemdur = 251; break;
- case 267 : maxhelditemdur = 251; break;
- case 268 : maxhelditemdur = 60; break;
- case 269 : maxhelditemdur = 60; break;
- case 270 : maxhelditemdur = 60; break;
- case 271 : maxhelditemdur = 60; break;
- case 272 : maxhelditemdur = 132; break;
- case 273 : maxhelditemdur = 132; break;
- case 274 : maxhelditemdur = 132; break;
- case 275 : maxhelditemdur = 132; break;
- case 276 : maxhelditemdur = 1563; break;
- case 277 : maxhelditemdur = 1563; break;
- case 278 : maxhelditemdur = 1563; break;
- case 279 : maxhelditemdur = 1563; break;
- case 283 : maxhelditemdur = 32; break;
- case 284 : maxhelditemdur = 32; break;
- case 285 : maxhelditemdur = 32; break;
- case 286 : maxhelditemdur = 32; break;
- case 290 : maxhelditemdur = 60; break;
- case 291 : maxhelditemdur = 132; break;
- case 292 : maxhelditemdur = 251; break;
- case 293 : maxhelditemdur = 1563; break;
- case 294 : maxhelditemdur = 32; break;
- case 359 : maxhelditemdur = 251; break;
- }
- m_Player->GetInventory().GetEquippedItem().m_ItemHealth ++;
- LOG("Health: %i", m_Player->GetInventory().GetEquippedItem().m_ItemHealth);
- if (m_Player->GetInventory().GetEquippedItem().m_ItemHealth >= maxhelditemdur)
- {
- LOG("Player %s Broke ID: %i", GetUsername(), m_Player->GetInventory().GetEquippedItem().m_ItemID);
- m_Player->GetInventory().RemoveItem( m_Player->GetInventory().GetEquippedItem());
- }
- }
+
+ m_Player->UseEquippedItem();
}
}
}
@@ -901,6 +849,7 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) char MetaData = (char)Equipped.m_ItemHealth;
bool LavaBucket = false;
bool WaterBucket = false;
+ bool bRemoveItem = true;
switch( PacketData->m_ItemType ) // Special handling for special items
{
@@ -1022,6 +971,11 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) PacketData->m_ItemType = E_BLOCK_WALLSIGN;
}
break;
+ case E_ITEM_FLINT_AND_STEEL:
+ PacketData->m_ItemType = E_ITEM_FIRE;
+ m_Player->UseEquippedItem();
+ bRemoveItem = false;
+ break;
default:
break;
};
@@ -1058,23 +1012,28 @@ void cClientHandle::HandlePacket( cPacket* a_Packet ) break; //happens when you place a block aiming at side of block like torch or stem
}
- if( (m_Player->GetGameMode() == 1) || (m_Player->GetInventory().RemoveItem( Item )) )
+ if(bRemoveItem)
{
- if (isDoor) {
- if ( ( m_Player->GetWorld()->GetBlock( X, Y+1, Z ) == E_BLOCK_AIR ) || ( m_Player->GetWorld()->GetBlock( X, Y+1, Z ) == E_BLOCK_AIR ) ) {
- m_Player->GetWorld()->SetBlock( X, Y+1, Z, (char)PacketData->m_ItemType, MetaData + 8 );
-
- m_Player->GetWorld()->SetBlock( X, Y, Z, (char)PacketData->m_ItemType, MetaData );
- }
- } else {
+ if((m_Player->GetGameMode() != 1) && !m_Player->GetInventory().RemoveItem( Item ))
+ break;
+ }
+ if (isDoor)
+ {
+ if ( ( m_Player->GetWorld()->GetBlock( X, Y+1, Z ) == E_BLOCK_AIR ) || ( m_Player->GetWorld()->GetBlock( X, Y+1, Z ) == E_BLOCK_AIR ) )
+ {
+ m_Player->GetWorld()->SetBlock( X, Y+1, Z, (char)PacketData->m_ItemType, MetaData + 8 );
m_Player->GetWorld()->SetBlock( X, Y, Z, (char)PacketData->m_ItemType, MetaData );
}
- if (UpdateRedstone) {
- cRedstone Redstone(m_Player->GetWorld());
- Redstone.ChangeRedstone( PacketData->m_PosX, PacketData->m_PosY+1, PacketData->m_PosZ, AddedCurrent );
- }
+ } else {
+ m_Player->GetWorld()->SetBlock( X, Y, Z, (char)PacketData->m_ItemType, MetaData );
+ }
+ if (UpdateRedstone)
+ {
+ cRedstone Redstone(m_Player->GetWorld());
+ Redstone.ChangeRedstone( PacketData->m_PosX, PacketData->m_PosY+1, PacketData->m_PosZ, AddedCurrent );
}
+
}
}
/*
diff --git a/source/cFireSimulator.cpp b/source/cFireSimulator.cpp new file mode 100644 index 000000000..180ac9744 --- /dev/null +++ b/source/cFireSimulator.cpp @@ -0,0 +1,124 @@ +#include "cFireSimulator.h"
+#include "cWorld.h"
+#include "Vector3i.h"
+#include "BlockID.h"
+#include "Defines.h"
+#include <vector>
+
+cFireSimulator::cFireSimulator( cWorld* a_World )
+ : cSimulator(a_World)
+ , m_Blocks(new std::vector <Vector3i *>)
+ , m_Buffer(new std::vector <Vector3i *>)
+ , m_BurningBlocks(new std::vector <Vector3i *>)
+{
+
+}
+
+cFireSimulator::~cFireSimulator()
+{
+ delete m_Buffer;
+ delete m_Blocks;
+ delete m_BurningBlocks;
+}
+
+void cFireSimulator::Simulate( float a_Dt )
+{
+ m_Buffer->clear();
+ std::swap( m_Blocks, m_Buffer );
+
+ for( std::vector<Vector3i *>::iterator itr = m_Buffer->begin(); itr != m_Buffer->end(); ++itr )
+ {
+ Vector3i *Pos = *itr;
+
+ if(!IsAllowedBlock(m_World->GetBlock(Pos->x, Pos->y, Pos->z))) //Check wheather the block is still burning
+ continue;
+
+ if(BurnBlockAround(Pos->x, Pos->y, Pos->z)) //Burn single block and if there was one -> next time again
+ _AddBlock(Pos->x, Pos->y, Pos->z);
+ else
+ if(!IsForeverBurnable(m_World->GetBlock(Pos->x, Pos->y - 1, Pos->z)))
+ m_World->SetBlock(Pos->x, Pos->y, Pos->z, E_BLOCK_AIR, 0);
+
+ }
+
+}
+
+
+bool cFireSimulator::IsAllowedBlock( char a_BlockID )
+{
+ return a_BlockID == E_BLOCK_FIRE
+ || IsBlockLava(a_BlockID);
+}
+
+void cFireSimulator::AddBlock(int a_X, int a_Y, int a_Z)
+{
+ char BlockID = m_World->GetBlock(a_X, a_Y, a_Z);
+ if(!IsAllowedBlock(BlockID)) //This should save very much time because it doesn´t have to iterate through all blocks
+ return;
+
+ //check for duplicates
+ for( std::vector<Vector3i *>::iterator itr = m_Blocks->begin(); itr != m_Blocks->end(); ++itr )
+ {
+ Vector3i *Pos = *itr;
+ if( Pos->x == a_X && Pos->y == a_Y && Pos->z == a_Z )
+ return;
+ }
+
+ _AddBlock(a_X, a_Y, a_Z);
+
+}
+
+void cFireSimulator::_AddBlock(int a_X, int a_Y, int a_Z)
+{
+ Vector3i *Block = new Vector3i(a_X, a_Y, a_Z);
+ m_Blocks->push_back(Block);
+
+}
+
+bool cFireSimulator::IsForeverBurnable( char a_BlockID )
+{
+ return a_BlockID == E_BLOCK_BLOODSTONE;
+}
+
+bool cFireSimulator::IsBurnable( char a_BlockID )
+{
+ return a_BlockID == E_BLOCK_WOOD
+ || a_BlockID == E_BLOCK_LEAVES
+ || a_BlockID == E_BLOCK_LOG
+ || a_BlockID == E_BLOCK_WHITE_CLOTH
+ || a_BlockID == E_BLOCK_BOOKCASE
+ || a_BlockID == E_BLOCK_FENCE
+ || a_BlockID == E_BLOCK_TNT;
+}
+
+bool cFireSimulator::BurnBlockAround(int a_X, int a_Y, int a_Z)
+{
+ return BurnBlock(a_X + 1, a_Y, a_Z)
+ || BurnBlock(a_X - 1, a_Y, a_Z)
+ || BurnBlock(a_X, a_Y + 1, a_Z)
+ || BurnBlock(a_X, a_Y - 1, a_Z)
+ || BurnBlock(a_X, a_Y, a_Z + 1)
+ || BurnBlock(a_X, a_Y, a_Z - 1);
+}
+
+bool cFireSimulator::BurnBlock(int a_X, int a_Y, int a_Z)
+{
+ char BlockID = m_World->GetBlock(a_X, a_Y, a_Z);
+ if(IsBurnable(BlockID))
+ {
+ m_World->SetBlock(a_X, a_Y, a_Z, E_BLOCK_FIRE, 0);
+ return true;
+ }
+ if(IsForeverBurnable(BlockID))
+ {
+ char BlockAbove = m_World->GetBlock(a_X, a_Y + 1, a_Z);
+ if(BlockAbove == E_BLOCK_AIR)
+ {
+ m_World->SetBlock(a_X, a_Y + 1, a_Z, E_BLOCK_FIRE, 0); //Doesn´t notify the simulator so it won´t go off
+ return true;
+ }
+ return false;
+ }
+
+ return false;
+}
\ No newline at end of file diff --git a/source/cFireSimulator.h b/source/cFireSimulator.h new file mode 100644 index 000000000..b6ac627fb --- /dev/null +++ b/source/cFireSimulator.h @@ -0,0 +1,31 @@ +#pragma once
+#include "cSimulator.h"
+#include "cBlockEntity.h"
+#include "vector"
+
+class Vector3i;
+class cWorld;
+class cFireSimulator : public cSimulator
+{
+public:
+ cFireSimulator( cWorld* a_World );
+ ~cFireSimulator();
+
+ virtual void Simulate( float a_Dt );
+
+ virtual inline bool IsAllowedBlock( char a_BlockID );
+ virtual inline bool IsBurnable( char a_BlockID );
+
+ virtual inline bool IsForeverBurnable( char a_BlockID );
+
+protected:
+ virtual void AddBlock(int a_X, int a_Y, int a_Z);
+ virtual void _AddBlock(int a_X, int a_Y, int a_Z);
+ virtual inline bool BurnBlockAround(int a_X, int a_Y, int a_Z);
+ virtual inline bool BurnBlock(int a_X, int a_Y, int a_Z);
+
+ std::vector <Vector3i *> *m_Blocks;
+ std::vector <Vector3i *> *m_Buffer;
+
+ std::vector <Vector3i *> *m_BurningBlocks;
+};
\ No newline at end of file diff --git a/source/cItem.cpp b/source/cItem.cpp index 20720a6e8..1233f1287 100644 --- a/source/cItem.cpp +++ b/source/cItem.cpp @@ -41,4 +41,4 @@ bool cItem::IsEnchantable(ENUM_ITEM_ID item) return false;
-}
\ No newline at end of file +}
diff --git a/source/cItem.h b/source/cItem.h index c58079e87..c1b62495e 100644 --- a/source/cItem.h +++ b/source/cItem.h @@ -33,6 +33,58 @@ public: return ( (m_ItemID == a_Item.m_ItemID) && (m_ItemHealth == a_Item.m_ItemHealth) );
} //tolua_export
+ //TODO Sorry for writing the functions in the header. But somehow it doesn´t worked when I put them into the cpp File :s
+
+ inline int GetMaxDuration()
+ {
+ switch(m_ItemID)
+ {
+ case 256: return 251;
+ case 257: return 251;
+ case 258: return 251;
+ case 259: return 65; //Lighter / Flint and Steel
+ case 267: return 251;
+ case 268: return 60;
+ case 269: return 60;
+ case 270: return 60;
+ case 271: return 60;
+ case 272: return 132;
+ case 273: return 132;
+ case 274: return 132;
+ case 275: return 132;
+ case 276: return 1563;
+ case 277: return 1563;
+ case 278: return 1563;
+ case 279: return 1563;
+ case 283: return 32;
+ case 284: return 32;
+ case 285: return 32;
+ case 286: return 32;
+ case 290: return 60;
+ case 291: return 132;
+ case 292: return 251;
+ case 293: return 1563;
+ case 294: return 32;
+ case 359: return 251;
+ default: return 0;
+ }
+ }
+
+ //Damages a weapon. Returns true when destroyed
+ inline bool DamageItem() {
+ if(HasDuration())
+ {
+ m_ItemHealth++;
+
+ if(m_ItemHealth >= GetMaxDuration())
+ return true;
+
+ }
+ return false;
+ }
+
+ inline bool HasDuration() { return GetMaxDuration() > 0; }
+
void GetJson( Json::Value & a_OutValue ); //tolua_export
void FromJson( const Json::Value & a_Value ); //tolua_export
@@ -41,4 +93,5 @@ public: ENUM_ITEM_ID m_ItemID; //tolua_export
char m_ItemCount; //tolua_export
short m_ItemHealth; //tolua_export
+
}; //tolua_export
\ No newline at end of file diff --git a/source/cPlayer.cpp b/source/cPlayer.cpp index 7fbf1672b..92b16478a 100644 --- a/source/cPlayer.cpp +++ b/source/cPlayer.cpp @@ -830,4 +830,14 @@ const cPlayer::GroupList & cPlayer::GetGroups() const char* cPlayer::GetLoadedWorldName()
{
return m_pState->LoadedWorldName.c_str();
+}
+
+void cPlayer::UseEquippedItem()
+{
+ if(GetGameMode() != 1) //No damage in creative
+ if (GetInventory().GetEquippedItem().DamageItem())
+ {
+ LOG("Player %s Broke ID: %i", GetClientHandle()->GetUsername(), GetInventory().GetEquippedItem().m_ItemID);
+ GetInventory().RemoveItem( GetInventory().GetEquippedItem());
+ }
}
\ No newline at end of file diff --git a/source/cPlayer.h b/source/cPlayer.h index b0d446434..9f7535d7c 100644 --- a/source/cPlayer.h +++ b/source/cPlayer.h @@ -81,6 +81,8 @@ public: bool LoadFromDisk();
const char* GetLoadedWorldName();
+
+ void UseEquippedItem();
protected:
diff --git a/source/cWorld.cpp b/source/cWorld.cpp index 7e847d32c..501f78332 100644 --- a/source/cWorld.cpp +++ b/source/cWorld.cpp @@ -16,6 +16,7 @@ #include "cSimulatorManager.h"
#include "cWaterSimulator.h"
#include "cLavaSimulator.h"
+#include "cFireSimulator.h"
#include "cSandSimulator.h"
#include "cChicken.h"
#include "cSpider.h"
@@ -126,6 +127,7 @@ cWorld::~cWorld() delete m_SandSimulator;
delete m_WaterSimulator;
delete m_LavaSimulator;
+ delete m_FireSimulator;
UnloadUnusedChunks();
delete m_pState->pChunkGenerator;
@@ -240,11 +242,13 @@ cWorld::cWorld( const char* a_WorldName ) m_WaterSimulator = new cWaterSimulator( this );
m_LavaSimulator = new cLavaSimulator( this );
m_SandSimulator = new cSandSimulator(this);
+ m_FireSimulator = new cFireSimulator(this);
m_SimulatorManager = new cSimulatorManager();
m_SimulatorManager->RegisterSimulator(m_WaterSimulator, 6);
m_SimulatorManager->RegisterSimulator(m_LavaSimulator, 12);
m_SimulatorManager->RegisterSimulator(m_SandSimulator, 1);
+ m_SimulatorManager->RegisterSimulator(m_FireSimulator, 10);
memset( g_BlockLightValue, 0x0, 128 );
memset( g_BlockSpreadLightFalloff, 0xf, 128 ); // 0xf means total falloff
@@ -299,6 +303,7 @@ cWorld::cWorld( const char* a_WorldName ) g_BlockOneHitDig[ E_BLOCK_REDSTONE_REPEATER_OFF ] = true;
g_BlockOneHitDig[ E_BLOCK_REDSTONE_REPEATER_ON ] = true;
g_BlockOneHitDig[ E_BLOCK_LOCKED_CHEST ] = true;
+ g_BlockOneHitDig [ E_BLOCK_FIRE ] = true;
// Blocks that breaks when pushed by piston
g_BlockPistonBreakable[ E_BLOCK_AIR ] = true;
@@ -730,13 +735,15 @@ cChunk* cWorld::GetChunkOfBlock( int a_X, int a_Y, int a_Z ) void cWorld::SetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_BlockMeta )
{
- this->GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z);
-
- int ChunkX, ChunkY, ChunkZ;
- AbsoluteToRelative( a_X, a_Y, a_Z, ChunkX, ChunkY, ChunkZ );
+ int ChunkX, ChunkY, ChunkZ, X = a_X, Y = a_Y, Z = a_Z;
+ AbsoluteToRelative( X, Y, Z, ChunkX, ChunkY, ChunkZ );
cChunk* Chunk = GetChunk( ChunkX, ChunkY, ChunkZ );
- if( Chunk ) Chunk->SetBlock(a_X, a_Y, a_Z, a_BlockType, a_BlockMeta );
+ if( Chunk )
+ {
+ Chunk->SetBlock(X, Y, Z, a_BlockType, a_BlockMeta );
+ this->GetSimulatorManager()->WakeUp(a_X, a_Y, a_Z);
+ }
}
void cWorld::FastSetBlock( int a_X, int a_Y, int a_Z, char a_BlockType, char a_BlockMeta )
diff --git a/source/cWorld.h b/source/cWorld.h index 72c6975d1..47c60fb87 100644 --- a/source/cWorld.h +++ b/source/cWorld.h @@ -16,6 +16,7 @@ enum ENUM_ITEM_ID; class cPacket;
class cRedstone;
+class cFireSimulator;
class cWaterSimulator;
class cLavaSimulator;
class cSandSimulator;
@@ -184,6 +185,7 @@ private: cSandSimulator *m_SandSimulator;
cWaterSimulator* m_WaterSimulator;
cLavaSimulator* m_LavaSimulator;
+ cFireSimulator* m_FireSimulator;
cCriticalSection* m_ClientHandleCriticalSection;
cCriticalSection* m_EntitiesCriticalSection;
|