summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--SetFlags.cmake11
-rw-r--r--src/BlockInfo.cpp9
-rw-r--r--src/Blocks/BlockButton.h2
-rw-r--r--src/Blocks/BlockHandler.cpp4
-rw-r--r--src/Blocks/BlockLever.h4
-rw-r--r--src/Blocks/BlockStone.h2
-rw-r--r--src/Blocks/BlockTorch.h4
-rw-r--r--src/Blocks/BlockTripwire.h32
-rw-r--r--src/Blocks/BlockTripwireHook.h82
-rw-r--r--src/Chunk.cpp4
-rw-r--r--src/Chunk.h2
-rw-r--r--src/ChunkMap.cpp6
-rw-r--r--src/ChunkMap.h1
-rw-r--r--src/ClientHandle.cpp11
-rw-r--r--src/ClientHandle.h2
-rw-r--r--src/Entities/Entity.cpp5
-rw-r--r--src/Entities/Player.cpp2
-rw-r--r--src/Items/ItemHandler.cpp2
-rw-r--r--src/Items/ItemString.h39
-rw-r--r--src/Protocol/Protocol.h2
-rw-r--r--src/Protocol/Protocol125.cpp4
-rw-r--r--src/Protocol/Protocol125.h2
-rw-r--r--src/Protocol/Protocol132.cpp8
-rw-r--r--src/Protocol/Protocol132.h2
-rw-r--r--src/Protocol/Protocol17x.cpp4
-rw-r--r--src/Protocol/Protocol17x.h2
-rw-r--r--src/Protocol/ProtocolRecognizer.cpp4
-rw-r--r--src/Protocol/ProtocolRecognizer.h2
-rw-r--r--src/Simulator/FloodyFluidSimulator.cpp54
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.cpp163
-rw-r--r--src/Simulator/IncrementalRedstoneSimulator.h8
-rw-r--r--src/World.cpp11
-rw-r--r--src/World.h1
33 files changed, 404 insertions, 87 deletions
diff --git a/SetFlags.cmake b/SetFlags.cmake
index 290804fb6..339174e5c 100644
--- a/SetFlags.cmake
+++ b/SetFlags.cmake
@@ -26,10 +26,17 @@ endmacro()
macro(set_flags)
+ # Add coverage processing, if requested:
+ if (NOT MSVC)
+ if (${CMAKE_BUILD_TYPE} STREQUAL "COVERAGE")
+ message("Including CodeCoverage")
+ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/cmake-coverage/")
+ include(CodeCoverage)
+ endif()
+ endif()
+
# Add the preprocessor macros used for distinguishing between debug and release builds (CMake does this automatically for MSVC):
if (NOT MSVC)
- set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/lib/cmake-coverage/")
- include(CodeCoverage)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG")
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_COVERAGE} -D_DEBUG")
diff --git a/src/BlockInfo.cpp b/src/BlockInfo.cpp
index 26525e264..16314290a 100644
--- a/src/BlockInfo.cpp
+++ b/src/BlockInfo.cpp
@@ -101,6 +101,8 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_NEW_LEAVES ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_SIGN_POST ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_TORCH ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_TRIPWIRE ].m_SpreadLightFalloff = 1;
+ a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_VINES ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_WALLSIGN ].m_SpreadLightFalloff = 1;
a_Info[E_BLOCK_WOODEN_DOOR ].m_SpreadLightFalloff = 1;
@@ -160,6 +162,8 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_STATIONARY_WATER ].m_Transparent = true;
a_Info[E_BLOCK_STONE_BUTTON ].m_Transparent = true;
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_Transparent = true;
+ a_Info[E_BLOCK_TRIPWIRE ].m_Transparent = true;
+ a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_Transparent = true;
a_Info[E_BLOCK_TALL_GRASS ].m_Transparent = true;
a_Info[E_BLOCK_TORCH ].m_Transparent = true;
a_Info[E_BLOCK_VINES ].m_Transparent = true;
@@ -197,6 +201,7 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_TNT ].m_OneHitDig = true;
a_Info[E_BLOCK_TALL_GRASS ].m_OneHitDig = true;
a_Info[E_BLOCK_TORCH ].m_OneHitDig = true;
+ a_Info[E_BLOCK_TRIPWIRE ].m_OneHitDig = true;
// Blocks that break when pushed by piston:
@@ -239,6 +244,8 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_STONE_PRESSURE_PLATE].m_PistonBreakable = true;
a_Info[E_BLOCK_TALL_GRASS ].m_PistonBreakable = true;
a_Info[E_BLOCK_TORCH ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_TRIPWIRE ].m_PistonBreakable = true;
+ a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_PistonBreakable = true;
a_Info[E_BLOCK_VINES ].m_PistonBreakable = true;
a_Info[E_BLOCK_WATER ].m_PistonBreakable = true;
a_Info[E_BLOCK_WOODEN_BUTTON ].m_PistonBreakable = true;
@@ -280,6 +287,8 @@ void cBlockInfo::Initialize(cBlockInfoArray & a_Info)
a_Info[E_BLOCK_TALL_GRASS ].m_IsSnowable = false;
a_Info[E_BLOCK_TNT ].m_IsSnowable = false;
a_Info[E_BLOCK_TORCH ].m_IsSnowable = false;
+ a_Info[E_BLOCK_TRIPWIRE ].m_IsSnowable = false;
+ a_Info[E_BLOCK_TRIPWIRE_HOOK ].m_IsSnowable = false;
a_Info[E_BLOCK_VINES ].m_IsSnowable = false;
a_Info[E_BLOCK_WALLSIGN ].m_IsSnowable = false;
a_Info[E_BLOCK_WATER ].m_IsSnowable = false;
diff --git a/src/Blocks/BlockButton.h b/src/Blocks/BlockButton.h
index 4b2f6f618..7d9af207d 100644
--- a/src/Blocks/BlockButton.h
+++ b/src/Blocks/BlockButton.h
@@ -102,7 +102,7 @@ public:
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
- return (a_RelY > 0) && (cBlockInfo::IsSolid(BlockIsOn));
+ return (a_RelY > 0) && (cBlockInfo::FullyOccupiesVoxel(BlockIsOn));
}
} ;
diff --git a/src/Blocks/BlockHandler.cpp b/src/Blocks/BlockHandler.cpp
index 405c9bf43..3ddb7531d 100644
--- a/src/Blocks/BlockHandler.cpp
+++ b/src/Blocks/BlockHandler.cpp
@@ -65,6 +65,8 @@
#include "BlockRedstoneRepeater.h"
#include "BlockRedstoneTorch.h"
#include "BlockTNT.h"
+#include "BlockTripwire.h"
+#include "BlockTripwireHook.h"
#include "BlockSand.h"
#include "BlockSapling.h"
#include "BlockSideways.h"
@@ -291,6 +293,8 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
case E_BLOCK_TORCH: return new cBlockTorchHandler (a_BlockType);
case E_BLOCK_TRAPDOOR: return new cBlockTrapdoorHandler (a_BlockType);
case E_BLOCK_TNT: return new cBlockTNTHandler (a_BlockType);
+ case E_BLOCK_TRIPWIRE: return new cBlockTripwireHandler (a_BlockType);
+ case E_BLOCK_TRIPWIRE_HOOK: return new cBlockTripwireHookHandler (a_BlockType);
case E_BLOCK_VINES: return new cBlockVineHandler (a_BlockType);
case E_BLOCK_WALLSIGN: return new cBlockSignHandler (a_BlockType); // TODO: This needs a special handler
case E_BLOCK_WATER: return new cBlockFluidHandler (a_BlockType);
diff --git a/src/Blocks/BlockLever.h b/src/Blocks/BlockLever.h
index f1d3ff6d2..afe43abf8 100644
--- a/src/Blocks/BlockLever.h
+++ b/src/Blocks/BlockLever.h
@@ -22,7 +22,7 @@ public:
// Flip the ON bit on/off using the XOR bitwise operation
NIBBLETYPE Meta = (a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08);
- a_ChunkInterface.SetBlock(a_WorldInterface, a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_LEVER, Meta); // SetMeta doesn't work for unpowering levers, so setblock
+ a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
a_WorldInterface.GetBroadcastManager().BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
}
@@ -104,7 +104,7 @@ public:
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
- return (a_RelY > 0) && cBlockInfo::IsSolid(BlockIsOn);
+ return (a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn);
}
diff --git a/src/Blocks/BlockStone.h b/src/Blocks/BlockStone.h
index af4c6509a..cd5230f49 100644
--- a/src/Blocks/BlockStone.h
+++ b/src/Blocks/BlockStone.h
@@ -2,8 +2,6 @@
#pragma once
#include "BlockHandler.h"
-#include "../MersenneTwister.h"
-#include "../World.h"
diff --git a/src/Blocks/BlockTorch.h b/src/Blocks/BlockTorch.h
index 8ddec8de1..44c33c429 100644
--- a/src/Blocks/BlockTorch.h
+++ b/src/Blocks/BlockTorch.h
@@ -154,7 +154,11 @@ public:
if (
(BlockInQuestion == E_BLOCK_GLASS) ||
+ (BlockInQuestion == E_BLOCK_STAINED_GLASS) ||
(BlockInQuestion == E_BLOCK_FENCE) ||
+ (BlockInQuestion == E_BLOCK_SOULSAND) ||
+ (BlockInQuestion == E_BLOCK_MOB_SPAWNER) ||
+ (BlockInQuestion == E_BLOCK_END_PORTAL_FRAME) || // Actual vanilla behaviour
(BlockInQuestion == E_BLOCK_NETHER_BRICK_FENCE) ||
(BlockInQuestion == E_BLOCK_COBBLESTONE_WALL)
)
diff --git a/src/Blocks/BlockTripwire.h b/src/Blocks/BlockTripwire.h
new file mode 100644
index 000000000..3ab17bf4a
--- /dev/null
+++ b/src/Blocks/BlockTripwire.h
@@ -0,0 +1,32 @@
+
+#pragma once
+
+#include "BlockHandler.h"
+
+
+
+
+
+class cBlockTripwireHandler :
+ public cBlockHandler
+{
+public:
+ cBlockTripwireHandler(BLOCKTYPE a_BlockType)
+ : cBlockHandler(a_BlockType)
+ {
+ }
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ a_Pickups.push_back(cItem(E_ITEM_STRING, 1, 0));
+ }
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "";
+ }
+};
+
+
+
+
diff --git a/src/Blocks/BlockTripwireHook.h b/src/Blocks/BlockTripwireHook.h
new file mode 100644
index 000000000..f849fb8ad
--- /dev/null
+++ b/src/Blocks/BlockTripwireHook.h
@@ -0,0 +1,82 @@
+#pragma once
+
+#include "BlockHandler.h"
+#include "MetaRotator.h"
+
+
+
+
+
+class cBlockTripwireHookHandler :
+ public cMetaRotator<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01>
+{
+public:
+ cBlockTripwireHookHandler(BLOCKTYPE a_BlockType)
+ : cMetaRotator<cBlockHandler, 0x03, 0x02, 0x03, 0x00, 0x01>(a_BlockType)
+ {
+ }
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override
+ {
+ a_BlockType = m_BlockType;
+
+ a_BlockMeta = DirectionToMetadata(a_BlockFace);
+
+ return true;
+ }
+
+ inline static NIBBLETYPE DirectionToMetadata(eBlockFace a_Direction)
+ {
+ switch (a_Direction)
+ {
+ case BLOCK_FACE_XM: return 0x1;
+ case BLOCK_FACE_XP: return 0x3;
+ case BLOCK_FACE_ZM: return 0x2;
+ case BLOCK_FACE_ZP: return 0x0;
+ default: ASSERT(!"Unhandled tripwire hook direction!"); return 0x0;
+ }
+ }
+
+ inline static eBlockFace MetadataToDirection(NIBBLETYPE a_Meta)
+ {
+ switch (a_Meta & 0x03)
+ {
+ case 0x1: return BLOCK_FACE_XM;
+ case 0x3: return BLOCK_FACE_XP;
+ case 0x2: return BLOCK_FACE_ZM;
+ case 0x0: return BLOCK_FACE_ZP;
+ default: ASSERT(!"Unhandled tripwire hook metadata!"); return BLOCK_FACE_NONE;
+ }
+ }
+
+ virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
+ {
+ // Reset meta to 0
+ a_Pickups.push_back(cItem(E_BLOCK_TRIPWIRE_HOOK, 1, 0));
+ }
+
+ virtual bool CanBeAt(cChunkInterface & a_ChunkInterface, int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
+ {
+ NIBBLETYPE Meta;
+ a_Chunk.UnboundedRelGetBlockMeta(a_RelX, a_RelY, a_RelZ, Meta);
+
+ AddFaceDirection(a_RelX, a_RelY, a_RelZ, MetadataToDirection(Meta), true);
+ BLOCKTYPE BlockIsOn; a_Chunk.UnboundedRelGetBlockType(a_RelX, a_RelY, a_RelZ, BlockIsOn);
+
+ return (a_RelY > 0) && cBlockInfo::FullyOccupiesVoxel(BlockIsOn);
+ }
+
+ virtual const char * GetStepSound(void) override
+ {
+ return "step.wood";
+ }
+};
+
+
+
+
diff --git a/src/Chunk.cpp b/src/Chunk.cpp
index 1320d5ccd..0fee40cac 100644
--- a/src/Chunk.cpp
+++ b/src/Chunk.cpp
@@ -2701,7 +2701,7 @@ void cChunk::BroadcastChunkData(cChunkDataSerializer & a_Serializer, const cClie
-void cChunk::BroadcastCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude)
+void cChunk::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude)
{
for (cClientHandleList::iterator itr = m_LoadedByClient.begin(); itr != m_LoadedByClient.end(); ++itr )
{
@@ -2709,7 +2709,7 @@ void cChunk::BroadcastCollectPickup(const cPickup & a_Pickup, const cPlayer & a_
{
continue;
}
- (*itr)->SendCollectPickup(a_Pickup, a_Player);
+ (*itr)->SendCollectEntity(a_Entity, a_Player);
} // for itr - LoadedByClient[]
}
diff --git a/src/Chunk.h b/src/Chunk.h
index 7664a7afd..e9d964e05 100644
--- a/src/Chunk.h
+++ b/src/Chunk.h
@@ -279,7 +279,7 @@ public:
void BroadcastBlockBreakAnimation(int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage, const cClientHandle * a_Exclude = NULL);
void BroadcastBlockEntity (int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude = NULL);
void BroadcastChunkData (cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL);
- void BroadcastCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
+ void BroadcastCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item, const cClientHandle * a_Exclude = NULL);
diff --git a/src/ChunkMap.cpp b/src/ChunkMap.cpp
index d2ccca94e..c9fb0b59e 100644
--- a/src/ChunkMap.cpp
+++ b/src/ChunkMap.cpp
@@ -419,16 +419,16 @@ void cChunkMap::BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSeriali
-void cChunkMap::BroadcastCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude)
+void cChunkMap::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude)
{
cCSLock Lock(m_CSLayers);
- cChunkPtr Chunk = GetChunkNoGen(a_Pickup.GetChunkX(), ZERO_CHUNK_Y, a_Pickup.GetChunkZ());
+ cChunkPtr Chunk = GetChunkNoGen(a_Entity.GetChunkX(), ZERO_CHUNK_Y, a_Entity.GetChunkZ());
if (Chunk == NULL)
{
return;
}
// It's perfectly legal to broadcast packets even to invalid chunks!
- Chunk->BroadcastCollectPickup(a_Pickup, a_Player, a_Exclude);
+ Chunk->BroadcastCollectEntity(a_Entity, a_Player, a_Exclude);
}
diff --git a/src/ChunkMap.h b/src/ChunkMap.h
index 3ee0bab3c..433516490 100644
--- a/src/ChunkMap.h
+++ b/src/ChunkMap.h
@@ -70,6 +70,7 @@ public:
void BroadcastBlockBreakAnimation(int a_entityID, int a_blockX, int a_blockY, int a_blockZ, char a_stage, const cClientHandle * a_Exclude = NULL);
void BroadcastBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ, const cClientHandle * a_Exclude);
void BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL);
+ void BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
void BroadcastCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
void BroadcastDestroyEntity(const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityEffect(const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL);
diff --git a/src/ClientHandle.cpp b/src/ClientHandle.cpp
index 611995148..95dfaffb2 100644
--- a/src/ClientHandle.cpp
+++ b/src/ClientHandle.cpp
@@ -1081,12 +1081,7 @@ void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_Blo
void cClientHandle::FinishDigAnimation()
{
- if (
- !m_HasStartedDigging || // Hasn't received the DIG_STARTED packet
- (m_LastDigBlockX == -1) ||
- (m_LastDigBlockY == -1) ||
- (m_LastDigBlockZ == -1)
- )
+ if (!m_HasStartedDigging) // Hasn't received the DIG_STARTED packet
{
return;
}
@@ -2073,9 +2068,9 @@ void cClientHandle::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializ
-void cClientHandle::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
+void cClientHandle::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
- m_Protocol->SendCollectPickup(a_Pickup, a_Player);
+ m_Protocol->SendCollectEntity(a_Entity, a_Player);
}
diff --git a/src/ClientHandle.h b/src/ClientHandle.h
index 3e18cbdad..02bc0c719 100644
--- a/src/ClientHandle.h
+++ b/src/ClientHandle.h
@@ -123,7 +123,7 @@ public:
void SendChat (const AString & a_Message, eMessageType a_ChatPrefix, const AString & a_AdditionalData = "");
void SendChat (const cCompositeChat & a_Message);
void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer);
- void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player);
+ void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player);
void SendDestroyEntity (const cEntity & a_Entity);
void SendDisconnect (const AString & a_Reason);
void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ);
diff --git a/src/Entities/Entity.cpp b/src/Entities/Entity.cpp
index ee7ce06ac..2b256e766 100644
--- a/src/Entities/Entity.cpp
+++ b/src/Entities/Entity.cpp
@@ -1090,7 +1090,10 @@ void cEntity::HandleAir(void)
if (IsSubmerged())
{
- SetSpeedY(1); // Float in the water
+ if (!IsPlayer()) // Players control themselves
+ {
+ SetSpeedY(1); // Float in the water
+ }
// Either reduce air level or damage player
if (m_AirLevel < 1)
diff --git a/src/Entities/Player.cpp b/src/Entities/Player.cpp
index 7b4fd219d..0abe50d11 100644
--- a/src/Entities/Player.cpp
+++ b/src/Entities/Player.cpp
@@ -1913,7 +1913,7 @@ void cPlayer::HandleFood(void)
{
m_FoodTickTimer = 0;
- if (m_FoodLevel >= 17)
+ if ((m_FoodLevel > 17) && (GetHealth() < GetMaxHealth()))
{
// Regenerate health from food, incur 3 pts of food exhaustion:
Heal(1);
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index f639423ae..a2fd4e3f8 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -44,6 +44,7 @@
#include "ItemSign.h"
#include "ItemMobHead.h"
#include "ItemSpawnEgg.h"
+#include "ItemString.h"
#include "ItemSugarcane.h"
#include "ItemSword.h"
@@ -129,6 +130,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_ITEM_HEAD: return new cItemMobHeadHandler(a_ItemType);
case E_ITEM_SNOWBALL: return new cItemSnowballHandler();
case E_ITEM_SPAWN_EGG: return new cItemSpawnEggHandler(a_ItemType);
+ case E_ITEM_STRING: return new cItemStringHandler(a_ItemType);
case E_ITEM_SUGARCANE: return new cItemSugarcaneHandler(a_ItemType);
case E_ITEM_WOODEN_HOE:
diff --git a/src/Items/ItemString.h b/src/Items/ItemString.h
new file mode 100644
index 000000000..a97fbe0ce
--- /dev/null
+++ b/src/Items/ItemString.h
@@ -0,0 +1,39 @@
+
+#pragma once
+
+#include "ItemHandler.h"
+
+
+
+
+
+class cItemStringHandler :
+ public cItemHandler
+{
+public:
+ cItemStringHandler(int a_ItemType) :
+ cItemHandler(a_ItemType)
+ {
+ }
+
+ virtual bool IsPlaceable(void) override
+ {
+ return true;
+ }
+
+ virtual bool GetPlacementBlockTypeMeta(
+ cWorld * a_World, cPlayer * a_Player,
+ int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ int a_CursorX, int a_CursorY, int a_CursorZ,
+ BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
+ ) override
+ {
+ a_BlockType = E_BLOCK_TRIPWIRE;
+ a_BlockMeta = 0;
+ return true;
+ }
+};
+
+
+
+
diff --git a/src/Protocol/Protocol.h b/src/Protocol/Protocol.h
index c6e569919..e08a5a51b 100644
--- a/src/Protocol/Protocol.h
+++ b/src/Protocol/Protocol.h
@@ -64,7 +64,7 @@ public:
virtual void SendChat (const AString & a_Message) = 0;
virtual void SendChat (const cCompositeChat & a_Message) = 0;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) = 0;
- virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) = 0;
+ virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) = 0;
virtual void SendDestroyEntity (const cEntity & a_Entity) = 0;
virtual void SendDisconnect (const AString & a_Reason) = 0;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; ///< Request the client to open up the sign editor for the sign (1.6+)
diff --git a/src/Protocol/Protocol125.cpp b/src/Protocol/Protocol125.cpp
index 491058919..d53427bf7 100644
--- a/src/Protocol/Protocol125.cpp
+++ b/src/Protocol/Protocol125.cpp
@@ -274,11 +274,11 @@ void cProtocol125::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize
-void cProtocol125::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
+void cProtocol125::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_COLLECT_PICKUP);
- WriteInt (a_Pickup.GetUniqueID());
+ WriteInt (a_Entity.GetUniqueID());
WriteInt (a_Player.GetUniqueID());
Flush();
}
diff --git a/src/Protocol/Protocol125.h b/src/Protocol/Protocol125.h
index 85418f71f..747bf512d 100644
--- a/src/Protocol/Protocol125.h
+++ b/src/Protocol/Protocol125.h
@@ -36,7 +36,7 @@ public:
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
- virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override;
+ virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendDisconnect (const AString & a_Reason) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
diff --git a/src/Protocol/Protocol132.cpp b/src/Protocol/Protocol132.cpp
index 1e3fc8de8..31cf99f53 100644
--- a/src/Protocol/Protocol132.cpp
+++ b/src/Protocol/Protocol132.cpp
@@ -188,19 +188,19 @@ void cProtocol132::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize
-void cProtocol132::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
+void cProtocol132::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
cCSLock Lock(m_CSPacket);
WriteByte(PACKET_COLLECT_PICKUP);
- WriteInt (a_Pickup.GetUniqueID());
+ WriteInt (a_Entity.GetUniqueID());
WriteInt (a_Player.GetUniqueID());
Flush();
// Also send the "pop" sound effect with a somewhat random pitch (fast-random using EntityID ;)
SendSoundEffect(
"random.pop",
- (int)(a_Pickup.GetPosX() * 8), (int)(a_Pickup.GetPosY() * 8), (int)(a_Pickup.GetPosZ() * 8),
- 0.5, (float)(0.75 + ((float)((a_Pickup.GetUniqueID() * 23) % 32)) / 64)
+ (int)(a_Entity.GetPosX() * 8), (int)(a_Entity.GetPosY() * 8), (int)(a_Entity.GetPosZ() * 8),
+ 0.5, (float)(0.75 + ((float)((a_Entity.GetUniqueID() * 23) % 32)) / 64)
);
}
diff --git a/src/Protocol/Protocol132.h b/src/Protocol/Protocol132.h
index 32bc7d581..e5d3ee80c 100644
--- a/src/Protocol/Protocol132.h
+++ b/src/Protocol/Protocol132.h
@@ -48,7 +48,7 @@ public:
virtual void SendBlockBreakAnim (int a_EntityID, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Stage) override;
virtual void SendBlockChange (int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
- virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override;
+ virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendEntityEquipment (const cEntity & a_Entity, short a_SlotNum, const cItem & a_Item) override;
virtual void SendLogin (const cPlayer & a_Player, const cWorld & a_World) override;
diff --git a/src/Protocol/Protocol17x.cpp b/src/Protocol/Protocol17x.cpp
index 02c577dc8..49fef0b8e 100644
--- a/src/Protocol/Protocol17x.cpp
+++ b/src/Protocol/Protocol17x.cpp
@@ -351,12 +351,12 @@ void cProtocol172::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerialize
-void cProtocol172::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
+void cProtocol172::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
ASSERT(m_State == 3); // In game mode?
cPacketizer Pkt(*this, 0x0d); // Collect Item packet
- Pkt.WriteInt(a_Pickup.GetUniqueID());
+ Pkt.WriteInt(a_Entity.GetUniqueID());
Pkt.WriteInt(a_Player.GetUniqueID());
}
diff --git a/src/Protocol/Protocol17x.h b/src/Protocol/Protocol17x.h
index 8be1d9211..07c8c8459 100644
--- a/src/Protocol/Protocol17x.h
+++ b/src/Protocol/Protocol17x.h
@@ -68,7 +68,7 @@ public:
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
- virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override;
+ virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendDisconnect (const AString & a_Reason) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
diff --git a/src/Protocol/ProtocolRecognizer.cpp b/src/Protocol/ProtocolRecognizer.cpp
index 80f5da25a..2436c49c3 100644
--- a/src/Protocol/ProtocolRecognizer.cpp
+++ b/src/Protocol/ProtocolRecognizer.cpp
@@ -181,10 +181,10 @@ void cProtocolRecognizer::SendChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSe
-void cProtocolRecognizer::SendCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player)
+void cProtocolRecognizer::SendCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player)
{
ASSERT(m_Protocol != NULL);
- m_Protocol->SendCollectPickup(a_Pickup, a_Player);
+ m_Protocol->SendCollectEntity(a_Entity, a_Player);
}
diff --git a/src/Protocol/ProtocolRecognizer.h b/src/Protocol/ProtocolRecognizer.h
index 5e178447c..a5a6c59b6 100644
--- a/src/Protocol/ProtocolRecognizer.h
+++ b/src/Protocol/ProtocolRecognizer.h
@@ -71,7 +71,7 @@ public:
virtual void SendChat (const AString & a_Message) override;
virtual void SendChat (const cCompositeChat & a_Message) override;
virtual void SendChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer) override;
- virtual void SendCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player) override;
+ virtual void SendCollectEntity (const cEntity & a_Entity, const cPlayer & a_Player) override;
virtual void SendDestroyEntity (const cEntity & a_Entity) override;
virtual void SendDisconnect (const AString & a_Reason) override;
virtual void SendEditSign (int a_BlockX, int a_BlockY, int a_BlockZ) override; ///< Request the client to open up the sign editor for the sign (1.6+)
diff --git a/src/Simulator/FloodyFluidSimulator.cpp b/src/Simulator/FloodyFluidSimulator.cpp
index e95af3a1c..4ffda2365 100644
--- a/src/Simulator/FloodyFluidSimulator.cpp
+++ b/src/Simulator/FloodyFluidSimulator.cpp
@@ -217,14 +217,20 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
{
ASSERT(a_NewMeta <= 8); // Invalid meta values
ASSERT(a_NewMeta > 0); // Source blocks aren't spread
-
- BLOCKTYPE BlockType;
- NIBBLETYPE BlockMeta;
- if (!a_NearChunk->UnboundedRelGetBlock(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta))
+
+ a_NearChunk = a_NearChunk->GetRelNeighborChunkAdjustCoords(a_RelX, a_RelZ);
+ if ((a_NearChunk == NULL) || (!a_NearChunk->IsValid()))
{
// Chunk not available
return;
}
+
+ const int BlockX = a_NearChunk->GetPosX() * cChunkDef::Width + a_RelX;
+ const int BlockZ = a_NearChunk->GetPosZ() * cChunkDef::Width + a_RelZ;
+
+ BLOCKTYPE BlockType;
+ NIBBLETYPE BlockMeta;
+ a_NearChunk->GetBlockTypeMeta(a_RelX, a_RelY, a_RelZ, BlockType, BlockMeta);
if (IsAllowedBlock(BlockType))
{
@@ -246,15 +252,9 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
a_RelX, a_RelY, a_RelZ,
ItemTypeToString(NewBlock).c_str()
);
- a_NearChunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);
+ a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);
- int BaseX = a_NearChunk->GetPosX() * cChunkDef::Width;
- int BaseZ = a_NearChunk->GetPosZ() * cChunkDef::Width;
-
- BaseX += a_RelX;
- BaseZ += a_RelZ;
-
- a_NearChunk->BroadcastSoundEffect("random.fizz", BaseX * 8, a_RelY * 8, BaseZ * 8, 0.5f, 1.5f);
+ a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f);
return;
}
}
@@ -267,15 +267,9 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
FLOG(" Water flowing into lava, turning lava at rel {%d, %d, %d} into %s",
a_RelX, a_RelY, a_RelZ, ItemTypeToString(NewBlock).c_str()
);
- a_NearChunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);
-
- int BaseX = a_NearChunk->GetPosX() * cChunkDef::Width;
- int BaseZ = a_NearChunk->GetPosZ() * cChunkDef::Width;
-
- BaseX += a_RelX;
- BaseZ += a_RelZ;
+ a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, NewBlock, 0);
- a_NearChunk->BroadcastSoundEffect("random.fizz", BaseX * 8, a_RelY * 8, BaseZ * 8, 0.5f, 1.5f);
+ a_NearChunk->BroadcastSoundEffect("random.fizz", BlockX * 8, a_RelY * 8, BlockZ * 8, 0.5f, 1.5f);
return;
}
}
@@ -303,21 +297,17 @@ void cFloodyFluidSimulator::SpreadToNeighbor(cChunk * a_NearChunk, int a_RelX, i
m_World,
PluginInterface,
NULL,
- a_NearChunk->GetPosX() * cChunkDef::Width + a_RelX,
+ BlockX,
a_RelY,
- a_NearChunk->GetPosZ() * cChunkDef::Width + a_RelZ
+ BlockZ
);
}
} // if (CanWashAway)
-
+
// Spread:
- FLOG(" Spreading to {%d, %d, %d} with meta %d",
- a_NearChunk->GetPosX() * cChunkDef::Width + a_RelX,
- a_RelY,
- a_NearChunk->GetPosZ() * cChunkDef::Width + a_RelZ,
- a_NewMeta
- );
- a_NearChunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta);
+ FLOG(" Spreading to {%d, %d, %d} with meta %d", BlockX, a_RelY, BlockZ, a_NewMeta);
+ a_NearChunk->SetBlock(a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta);
+ m_World.GetSimulatorManager()->WakeUp(BlockX, a_RelY, BlockZ, a_NearChunk);
HardenBlock(a_NearChunk, a_RelX, a_RelY, a_RelZ, m_FluidBlock, a_NewMeta);
}
@@ -409,13 +399,13 @@ bool cFloodyFluidSimulator::HardenBlock(cChunk * a_Chunk, int a_RelX, int a_RelY
if (a_Meta == 0)
{
// Source lava block
- a_Chunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_OBSIDIAN, 0);
+ a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_OBSIDIAN, 0);
return true;
}
// Ignore last lava level
else if (a_Meta <= 4)
{
- a_Chunk->UnboundedRelSetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_COBBLESTONE, 0);
+ a_Chunk->SetBlock(a_RelX, a_RelY, a_RelZ, E_BLOCK_COBBLESTONE, 0);
return true;
}
}
diff --git a/src/Simulator/IncrementalRedstoneSimulator.cpp b/src/Simulator/IncrementalRedstoneSimulator.cpp
index 10446a879..866a5b65a 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.cpp
+++ b/src/Simulator/IncrementalRedstoneSimulator.cpp
@@ -2,6 +2,7 @@
#include "Globals.h" // NOTE: MSVC stupidness requires this to be the same across all modules
#include "IncrementalRedstoneSimulator.h"
+#include "BoundingBox.h"
#include "../BlockEntities/DropSpenserEntity.h"
#include "../BlockEntities/NoteEntity.h"
#include "../BlockEntities/CommandBlockEntity.h"
@@ -12,10 +13,13 @@
#include "../Blocks/BlockButton.h"
#include "../Blocks/BlockLever.h"
#include "../Blocks/BlockPiston.h"
+#include "../Blocks/BlockTripwireHook.h"
+
+#define WAKE_SIMULATOR_IF_DIRTY(a_Chunk, a_BlockX, a_BlockY, a_BlockZ) if (a_Chunk->IsRedstoneDirty()) WakeUp(a_BlockX, a_BlockY, a_BlockZ, a_Chunk);
+
-
cIncrementalRedstoneSimulator::cIncrementalRedstoneSimulator(cWorld & a_World) :
super(a_World),
@@ -99,10 +103,11 @@ void cIncrementalRedstoneSimulator::RedstoneAddBlock(int a_BlockX, int a_BlockY,
// Changeable sources
((Block == E_BLOCK_REDSTONE_WIRE) && (Meta == 0)) ||
((Block == E_BLOCK_LEVER) && !IsLeverOn(Meta)) ||
- ((Block == E_BLOCK_DETECTOR_RAIL) && (Meta & 0x08) == 0) ||
+ ((Block == E_BLOCK_DETECTOR_RAIL) && ((Meta & 0x08) == 0)) ||
(((Block == E_BLOCK_STONE_BUTTON) || (Block == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(Meta))) ||
(((Block == E_BLOCK_STONE_PRESSURE_PLATE) || (Block == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (Meta == 0)) ||
- (((Block == E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE) || (Block == E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE)) && (Meta == 0))
+ (((Block == E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE) || (Block == E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE)) && (Meta == 0)) ||
+ ((Block == E_BLOCK_TRIPWIRE_HOOK) && ((Meta & 0x08) == 0))
)
{
LOGD("cIncrementalRedstoneSimulator: Erased block @ {%i, %i, %i} from powered blocks list due to present/past metadata mismatch", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z);
@@ -289,6 +294,9 @@ void cIncrementalRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int
switch (dataitr->Data)
{
case E_BLOCK_DAYLIGHT_SENSOR: HandleDaylightSensor(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_TRIPWIRE: HandleTripwire(dataitr->x, dataitr->y, dataitr->z); break;
+ case E_BLOCK_TRIPWIRE_HOOK: HandleTripwireHook(dataitr->x, dataitr->y, dataitr->z); break;
+
case E_BLOCK_WOODEN_PRESSURE_PLATE:
case E_BLOCK_STONE_PRESSURE_PLATE:
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
@@ -1120,7 +1128,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
case E_BLOCK_STONE_PRESSURE_PLATE:
{
// MCS feature - stone pressure plates can only be triggered by players :D
- cPlayer * a_Player = m_World.FindClosestPlayer(Vector3f(BlockX + 0.5f, (float)a_RelBlockY, BlockZ + 0.5f), 0.7f, false);
+ cPlayer * a_Player = m_World.FindClosestPlayer(Vector3f(BlockX + 0.5f, (float)a_RelBlockY, BlockZ + 0.5f), 0.5f, false);
if (a_Player != NULL)
{
@@ -1131,7 +1139,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
else
{
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0);
- m_World.WakeUpSimulators(BlockX, a_RelBlockY, BlockZ);
+ WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
}
break;
}
@@ -1155,7 +1163,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
double Distance = (EntityPos - BlockPos).Length();
- if (Distance <= 0.7)
+ if (Distance <= 0.5)
{
m_NumberOfEntities++;
}
@@ -1177,7 +1185,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
};
cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ);
- m_World.ForEachEntity(PressurePlateCallback);
+ m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback);
unsigned char Power;
NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
@@ -1198,7 +1206,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
- m_World.WakeUpSimulators(BlockX, a_RelBlockY, BlockZ);
+ WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
}
break;
@@ -1223,7 +1231,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
double Distance = (EntityPos - BlockPos).Length();
- if (Distance <= 0.7)
+ if (Distance <= 0.5)
{
m_NumberOfEntities++;
}
@@ -1232,7 +1240,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
bool GetPowerLevel(unsigned char & a_PowerLevel) const
{
- a_PowerLevel = std::min((int)ceil(m_NumberOfEntities / (float)10), MAX_POWER_LEVEL);
+ a_PowerLevel = std::min((int)ceil(m_NumberOfEntities / 10.f), MAX_POWER_LEVEL);
return (a_PowerLevel > 0);
}
@@ -1245,7 +1253,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
};
cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ);
- m_World.ForEachEntity(PressurePlateCallback);
+ m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback);
unsigned char Power;
NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
@@ -1266,7 +1274,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
- m_World.WakeUpSimulators(BlockX, a_RelBlockY, BlockZ);
+ WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
}
break;
@@ -1291,7 +1299,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
double Distance = (EntityPos - BlockPos).Length();
- if (Distance <= 0.7)
+ if (Distance <= 0.5)
{
m_FoundEntity = true;
return true; // Break out, we only need to know for plates that at least one entity is on top
@@ -1313,7 +1321,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
} ;
cPressurePlateCallback PressurePlateCallback(BlockX, a_RelBlockY, BlockZ);
- m_World.ForEachEntity(PressurePlateCallback);
+ m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), PressurePlateCallback);
NIBBLETYPE Meta = m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
if (PressurePlateCallback.FoundEntity())
@@ -1333,7 +1341,7 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
m_Chunk->BroadcastSoundEffect("random.click", (int)((BlockX + 0.5) * 8.0), (int)((a_RelBlockY + 0.1) * 8.0), (int)((BlockZ + 0.5) * 8.0), 0.3F, 0.6F);
}
m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, E_META_PRESSURE_PLATE_RAISED);
- m_World.WakeUpSimulators(BlockX, a_RelBlockY, BlockZ);
+ WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
}
break;
}
@@ -1349,6 +1357,131 @@ void cIncrementalRedstoneSimulator::HandlePressurePlate(int a_RelBlockX, int a_R
+void cIncrementalRedstoneSimulator::HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
+{
+ int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
+ int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
+ int RelX = a_RelBlockX, RelZ = a_RelBlockZ;
+ bool FoundActivated = false;
+ eBlockFace FaceToGoTowards = cBlockTripwireHookHandler::MetadataToDirection(m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ));
+
+ for (int i = 0; i < 40; ++i) // Tripwires can be connected up to 40 blocks
+ {
+ BLOCKTYPE Type;
+ NIBBLETYPE Meta;
+
+ AddFaceDirection(RelX, a_RelBlockY, RelZ, FaceToGoTowards);
+ m_Chunk->UnboundedRelGetBlock(RelX, a_RelBlockY, RelZ, Type, Meta);
+
+ if (Type == E_BLOCK_TRIPWIRE)
+ {
+ if (Meta == 0x1)
+ {
+ FoundActivated = true;
+ }
+ }
+ else if (Type == E_BLOCK_TRIPWIRE_HOOK)
+ {
+ if (ReverseBlockFace(cBlockTripwireHookHandler::MetadataToDirection(Meta)) == FaceToGoTowards)
+ {
+ // Other hook not facing in opposite direction
+ break;
+ }
+ else
+ {
+ // Tripwire hook not connected at all, AND away all the power state bits
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3);
+ WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ return;
+ }
+ }
+ else
+ {
+ // Tripwire hook not connected at all, AND away all the power state bits
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x3);
+ WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ return;
+ }
+ }
+
+ if (FoundActivated)
+ {
+ // Connected and activated, set the 3rd and 4th highest bits
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) | 0xC);
+ SetAllDirsAsPowered(a_RelBlockX, a_RelBlockY, a_RelBlockZ);
+ }
+ else
+ {
+ // Connected but not activated, AND away the highest bit
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, (m_Chunk->GetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ) & 0x7) | 0x4);
+ WAKE_SIMULATOR_IF_DIRTY(m_Chunk, BlockX, a_RelBlockY, BlockZ);
+ }
+}
+
+
+
+
+
+void cIncrementalRedstoneSimulator::HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
+{
+ int BlockX = m_Chunk->GetPosX() * cChunkDef::Width + a_RelBlockX;
+ int BlockZ = m_Chunk->GetPosZ() * cChunkDef::Width + a_RelBlockZ;
+
+ class cTripwireCallback :
+ public cEntityCallback
+ {
+ public:
+ cTripwireCallback(int a_BlockX, int a_BlockY, int a_BlockZ) :
+ m_FoundEntity(false),
+ m_X(a_BlockX),
+ m_Y(a_BlockY),
+ m_Z(a_BlockZ)
+ {
+ }
+
+ virtual bool Item(cEntity * a_Entity) override
+ {
+ cBoundingBox bbWire(m_X, m_X + 1, m_Y, m_Y + 0.1, m_Z, m_Z + 1);
+ cBoundingBox bbEntity(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
+
+ if (bbEntity.DoesIntersect(bbWire))
+ {
+ m_FoundEntity = true;
+ return true; // One entity is sufficient to trigger the wire
+ }
+ return false;
+ }
+
+ bool FoundEntity(void) const
+ {
+ return m_FoundEntity;
+ }
+
+ protected:
+ bool m_FoundEntity;
+
+ int m_X;
+ int m_Y;
+ int m_Z;
+ };
+
+ cTripwireCallback TripwireCallback(BlockX, a_RelBlockY, BlockZ);
+ m_World.ForEachEntityInChunk(m_Chunk->GetPosX(), m_Chunk->GetPosZ(), TripwireCallback);
+
+ if (TripwireCallback.FoundEntity())
+ {
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x1);
+ }
+ else
+ {
+ m_Chunk->SetMeta(a_RelBlockX, a_RelBlockY, a_RelBlockZ, 0x0);
+ }
+}
+
+
+
+
+
bool cIncrementalRedstoneSimulator::AreCoordsDirectlyPowered(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ)
{
int BlockX = (m_Chunk->GetPosX() * cChunkDef::Width) + a_RelBlockX;
diff --git a/src/Simulator/IncrementalRedstoneSimulator.h b/src/Simulator/IncrementalRedstoneSimulator.h
index 9c1f9460c..6cefdebf2 100644
--- a/src/Simulator/IncrementalRedstoneSimulator.h
+++ b/src/Simulator/IncrementalRedstoneSimulator.h
@@ -102,6 +102,11 @@ private:
void HandleDaylightSensor(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles pressure plates */
void HandlePressurePlate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ, BLOCKTYPE a_MyType);
+ /** Handles tripwire hooks
+ Performs correct meta and power setting for self by going in the direction it faces and looking for a continous line of tripwire bounded by another oppositely facing hook
+ If this line is complete, it verifies that at least on wire reports an entity is on top (via its meta), and performs its task
+ */
+ void HandleTripwireHook(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/* ==================== */
/* ====== CARRIERS ====== */
@@ -134,6 +139,8 @@ private:
void HandleFenceGate(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/** Handles noteblocks */
void HandleNoteBlock(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
+ /** Handles tripwires */
+ void HandleTripwire(int a_RelBlockX, int a_RelBlockY, int a_RelBlockZ);
/* ===================== */
/* ====== Helper functions ====== */
@@ -271,6 +278,7 @@ private:
case E_BLOCK_TNT:
case E_BLOCK_TRAPDOOR:
case E_BLOCK_TRIPWIRE_HOOK:
+ case E_BLOCK_TRIPWIRE:
case E_BLOCK_WOODEN_BUTTON:
case E_BLOCK_WOODEN_DOOR:
case E_BLOCK_WOODEN_PRESSURE_PLATE:
diff --git a/src/World.cpp b/src/World.cpp
index 5b067b386..bd7694e96 100644
--- a/src/World.cpp
+++ b/src/World.cpp
@@ -1877,9 +1877,18 @@ void cWorld::BroadcastChunkData(int a_ChunkX, int a_ChunkZ, cChunkDataSerializer
+void cWorld::BroadcastCollectEntity(const cEntity & a_Entity, const cPlayer & a_Player, const cClientHandle * a_Exclude)
+{
+ m_ChunkMap->BroadcastCollectEntity(a_Entity, a_Player, a_Exclude);
+}
+
+
+
+
+
void cWorld::BroadcastCollectPickup(const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude)
{
- m_ChunkMap->BroadcastCollectPickup(a_Pickup, a_Player, a_Exclude);
+ m_ChunkMap->BroadcastCollectEntity(a_Pickup, a_Player, a_Exclude);
}
diff --git a/src/World.h b/src/World.h
index 2b7f78760..692d5a497 100644
--- a/src/World.h
+++ b/src/World.h
@@ -206,6 +206,7 @@ public:
// tolua_end
void BroadcastChunkData (int a_ChunkX, int a_ChunkZ, cChunkDataSerializer & a_Serializer, const cClientHandle * a_Exclude = NULL);
+ void BroadcastCollectEntity (const cEntity & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
void BroadcastCollectPickup (const cPickup & a_Pickup, const cPlayer & a_Player, const cClientHandle * a_Exclude = NULL);
void BroadcastDestroyEntity (const cEntity & a_Entity, const cClientHandle * a_Exclude = NULL);
void BroadcastEntityEffect (const cEntity & a_Entity, int a_EffectID, int a_Amplifier, short a_Duration, const cClientHandle * a_Exclude = NULL);