summaryrefslogtreecommitdiffstats
path: root/src/Items
diff options
context:
space:
mode:
Diffstat (limited to 'src/Items')
-rw-r--r--src/Items/CMakeLists.txt54
-rw-r--r--src/Items/ItemArmor.h43
-rw-r--r--src/Items/ItemBed.h2
-rw-r--r--src/Items/ItemBoat.h2
-rw-r--r--src/Items/ItemBow.h19
-rw-r--r--src/Items/ItemBrewingStand.h2
-rw-r--r--src/Items/ItemBucket.h81
-rw-r--r--src/Items/ItemCake.h2
-rw-r--r--src/Items/ItemCauldron.h2
-rw-r--r--src/Items/ItemComparator.h2
-rw-r--r--src/Items/ItemDoor.h6
-rw-r--r--src/Items/ItemFishingRod.h39
-rw-r--r--src/Items/ItemFlowerPot.h2
-rw-r--r--src/Items/ItemFood.h2
-rw-r--r--src/Items/ItemHandler.cpp173
-rw-r--r--src/Items/ItemHandler.h39
-rw-r--r--src/Items/ItemHoe.h10
-rw-r--r--src/Items/ItemItemFrame.h7
-rw-r--r--src/Items/ItemLeaves.h4
-rw-r--r--src/Items/ItemLighter.h6
-rw-r--r--src/Items/ItemLilypad.h18
-rw-r--r--src/Items/ItemMilk.h28
-rw-r--r--src/Items/ItemMinecart.h4
-rw-r--r--src/Items/ItemMobHead.h2
-rw-r--r--src/Items/ItemNetherWart.h2
-rw-r--r--src/Items/ItemPainting.h10
-rw-r--r--src/Items/ItemPickaxe.h19
-rw-r--r--src/Items/ItemPotion.h79
-rw-r--r--src/Items/ItemRedstoneDust.h4
-rw-r--r--src/Items/ItemRedstoneRepeater.h2
-rw-r--r--src/Items/ItemSapling.h2
-rw-r--r--src/Items/ItemSeeds.h8
-rw-r--r--src/Items/ItemShears.h27
-rw-r--r--src/Items/ItemShovel.h23
-rw-r--r--src/Items/ItemSign.h9
-rw-r--r--src/Items/ItemSpawnEgg.h40
-rw-r--r--src/Items/ItemString.h39
-rw-r--r--src/Items/ItemSugarcane.h2
-rw-r--r--src/Items/ItemSword.h36
-rw-r--r--src/Items/ItemThrowable.h21
40 files changed, 687 insertions, 185 deletions
diff --git a/src/Items/CMakeLists.txt b/src/Items/CMakeLists.txt
index a6fe6ea70..12a467672 100644
--- a/src/Items/CMakeLists.txt
+++ b/src/Items/CMakeLists.txt
@@ -4,9 +4,53 @@ project (MCServer)
include_directories ("${PROJECT_SOURCE_DIR}/../")
-file(GLOB SOURCE
- "*.cpp"
- "*.h"
-)
+SET (SRCS
+ ItemHandler.cpp)
-add_library(Items ${SOURCE})
+SET (HDRS
+ ItemArmor.h
+ ItemBed.h
+ ItemBoat.h
+ ItemBow.h
+ ItemBrewingStand.h
+ ItemBucket.h
+ ItemCake.h
+ ItemCauldron.h
+ ItemCloth.h
+ ItemComparator.h
+ ItemDoor.h
+ ItemDye.h
+ ItemEmptyMap.h
+ ItemFishingRod.h
+ ItemFlowerPot.h
+ ItemFood.h
+ ItemHandler.h
+ ItemHoe.h
+ ItemItemFrame.h
+ ItemLeaves.h
+ ItemLighter.h
+ ItemLilypad.h
+ ItemMap.h
+ ItemMilk.h
+ ItemMinecart.h
+ ItemMobHead.h
+ ItemNetherWart.h
+ ItemPainting.h
+ ItemPickaxe.h
+ ItemPotion.h
+ ItemRedstoneDust.h
+ ItemRedstoneRepeater.h
+ ItemSapling.h
+ ItemSeeds.h
+ ItemShears.h
+ ItemShovel.h
+ ItemSign.h
+ ItemSpawnEgg.h
+ ItemString.h
+ ItemSugarcane.h
+ ItemSword.h
+ ItemThrowable.h)
+
+if(NOT MSVC)
+ add_library(Items ${SRCS} ${HDRS})
+endif()
diff --git a/src/Items/ItemArmor.h b/src/Items/ItemArmor.h
index 08cddb1ad..2436df5bd 100644
--- a/src/Items/ItemArmor.h
+++ b/src/Items/ItemArmor.h
@@ -60,6 +60,49 @@ public:
return true;
}
+ virtual bool CanRepairWithRawMaterial(short a_ItemType) override
+ {
+ switch (m_ItemType)
+ {
+ case E_ITEM_CHAIN_BOOTS:
+ case E_ITEM_CHAIN_CHESTPLATE:
+ case E_ITEM_CHAIN_HELMET:
+ case E_ITEM_CHAIN_LEGGINGS:
+ {
+ return (a_ItemType == E_ITEM_IRON);
+ }
+ case E_ITEM_DIAMOND_BOOTS:
+ case E_ITEM_DIAMOND_CHESTPLATE:
+ case E_ITEM_DIAMOND_HELMET:
+ case E_ITEM_DIAMOND_LEGGINGS:
+ {
+ return (a_ItemType == E_ITEM_DIAMOND);
+ }
+ case E_ITEM_IRON_BOOTS:
+ case E_ITEM_IRON_CHESTPLATE:
+ case E_ITEM_IRON_HELMET:
+ case E_ITEM_IRON_LEGGINGS:
+ {
+ return (a_ItemType == E_ITEM_IRON);
+ }
+ case E_ITEM_GOLD_BOOTS:
+ case E_ITEM_GOLD_CHESTPLATE:
+ case E_ITEM_GOLD_HELMET:
+ case E_ITEM_GOLD_LEGGINGS:
+ {
+ return (a_ItemType == E_ITEM_GOLD);
+ }
+ case E_ITEM_LEATHER_BOOTS:
+ case E_ITEM_LEATHER_CAP:
+ case E_ITEM_LEATHER_PANTS:
+ case E_ITEM_LEATHER_TUNIC:
+ {
+ return (a_ItemType == E_ITEM_LEATHER);
+ }
+ }
+ return false;
+ }
+
} ;
diff --git a/src/Items/ItemBed.h b/src/Items/ItemBed.h
index f23d69731..94a14cf16 100644
--- a/src/Items/ItemBed.h
+++ b/src/Items/ItemBed.h
@@ -26,7 +26,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemBoat.h b/src/Items/ItemBoat.h
index 42f4ffc8f..7faac1e32 100644
--- a/src/Items/ItemBoat.h
+++ b/src/Items/ItemBoat.h
@@ -75,7 +75,7 @@ public:
double z = Callbacks.m_Pos.z;
cBoat * Boat = new cBoat(x + 0.5, y + 1, z + 0.5);
- Boat->Initialize(a_World);
+ Boat->Initialize(*a_World);
return true;
}
diff --git a/src/Items/ItemBow.h b/src/Items/ItemBow.h
index 8c0b3a0a3..e7a77dcbc 100644
--- a/src/Items/ItemBow.h
+++ b/src/Items/ItemBow.h
@@ -46,34 +46,31 @@ public:
{
// Actual shot - produce the arrow with speed based on the ticks that the bow was charged
ASSERT(a_Player != NULL);
-
+
int BowCharge = a_Player->FinishChargingBow();
- double Force = (double)BowCharge / 20;
- Force = (Force * Force + 2 * Force) / 3; // This formula is used by the 1.6.2 client
+ double Force = (double)BowCharge / 20.0;
+ Force = (Force * Force + 2.0 * Force) / 3.0; // This formula is used by the 1.6.2 client
if (Force < 0.1)
{
// Too little force, ignore the shot
return;
}
- if (Force > 1)
- {
- Force = 1;
- }
-
+ Force = std::min(Force, 1.0);
+
// Create the arrow entity:
cArrowEntity * Arrow = new cArrowEntity(*a_Player, Force * 2);
if (Arrow == NULL)
{
return;
}
- if (!Arrow->Initialize(a_Player->GetWorld()))
+ if (!Arrow->Initialize(*a_Player->GetWorld()))
{
delete Arrow;
+ Arrow = NULL;
return;
}
- a_Player->GetWorld()->BroadcastSpawnEntity(*Arrow);
- a_Player->GetWorld()->BroadcastSoundEffect("random.bow", (int)a_Player->GetPosX() * 8, (int)a_Player->GetPosY() * 8, (int)a_Player->GetPosZ() * 8, 0.5, (float)Force);
+ a_Player->GetWorld()->BroadcastSoundEffect("random.bow", a_Player->GetPosX(), a_Player->GetPosY(), a_Player->GetPosZ(), 0.5, (float)Force);
if (!a_Player->IsGameModeCreative())
{
a_Player->UseEquippedItem();
diff --git a/src/Items/ItemBrewingStand.h b/src/Items/ItemBrewingStand.h
index d5eefb855..7be57763c 100644
--- a/src/Items/ItemBrewingStand.h
+++ b/src/Items/ItemBrewingStand.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemBucket.h b/src/Items/ItemBucket.h
index 68c89dd85..a17c4838b 100644
--- a/src/Items/ItemBucket.h
+++ b/src/Items/ItemBucket.h
@@ -41,7 +41,7 @@ public:
bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{
- if (a_BlockFace > 0)
+ if (a_BlockFace != BLOCK_FACE_NONE)
{
return false;
}
@@ -49,7 +49,7 @@ public:
Vector3i BlockPos;
if (!GetBlockFromTrace(a_World, a_Player, BlockPos))
{
- return false; // Nothing in range.
+ return false; // Nothing in range.
}
if (a_World->GetBlockMeta(BlockPos.x, BlockPos.y, BlockPos.z) != 0)
@@ -94,30 +94,16 @@ public:
bool PlaceFluid(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, BLOCKTYPE a_FluidBlock)
- {
- if (a_BlockFace < 0)
+ {
+ if (a_BlockFace != BLOCK_FACE_NONE)
{
return false;
}
- BLOCKTYPE CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- bool CanWashAway = cFluidSimulator::CanWashAway(CurrentBlock);
- if (!CanWashAway)
+ BLOCKTYPE CurrentBlock;
+ Vector3i BlockPos;
+ if (!GetPlacementCoordsFromTrace(a_World, a_Player, BlockPos, CurrentBlock))
{
- // The block pointed at cannot be washed away, so put fluid on top of it / on its sides
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
- CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- }
- if (
- !CanWashAway &&
- (CurrentBlock != E_BLOCK_AIR) &&
- (CurrentBlock != E_BLOCK_WATER) &&
- (CurrentBlock != E_BLOCK_STATIONARY_WATER) &&
- (CurrentBlock != E_BLOCK_LAVA) &&
- (CurrentBlock != E_BLOCK_STATIONARY_LAVA)
- )
- {
- // Cannot place water here
return false;
}
@@ -131,14 +117,14 @@ public:
return false;
}
cItem Item(E_ITEM_BUCKET, 1);
- if (!a_Player->GetInventory().AddItem(Item,true,true))
+ if (!a_Player->GetInventory().AddItem(Item, true, true))
{
return false;
}
}
// Wash away anything that was there prior to placing:
- if (CanWashAway)
+ if (cFluidSimulator::CanWashAway(CurrentBlock))
{
cBlockHandler * Handler = BlockHandler(CurrentBlock);
if (Handler->DoesDropOnUnsuitable())
@@ -149,13 +135,13 @@ public:
}
}
- a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_FluidBlock, 0);
+ a_World->SetBlock(BlockPos.x, BlockPos.y, BlockPos.z, a_FluidBlock, 0);
return true;
}
- bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & BlockPos)
+ bool GetBlockFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos)
{
class cCallbacks :
public cBlockTracer::cCallbacks
@@ -174,7 +160,7 @@ public:
{
if (IsBlockWater(a_BlockType) || IsBlockLava(a_BlockType))
{
- if (a_BlockMeta != 0) // GetBlockFromTrace is called for scooping up fluids; the hit block should be a source
+ if (a_BlockMeta != 0) // GetBlockFromTrace is called for scooping up fluids; the hit block should be a source
{
return false;
}
@@ -198,8 +184,49 @@ public:
}
- BlockPos.Set(Callbacks.m_Pos.x, Callbacks.m_Pos.y, Callbacks.m_Pos.z);
+ a_BlockPos = Callbacks.m_Pos;
return true;
}
+
+
+ bool GetPlacementCoordsFromTrace(cWorld * a_World, cPlayer * a_Player, Vector3i & a_BlockPos, BLOCKTYPE & a_BlockType)
+ {
+ class cCallbacks :
+ public cBlockTracer::cCallbacks
+ {
+ public:
+ Vector3i m_Pos;
+ BLOCKTYPE m_ReplacedBlock;
+
+ virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
+ {
+ if (a_BlockType != E_BLOCK_AIR)
+ {
+ m_ReplacedBlock = a_BlockType;
+ if (!cFluidSimulator::CanWashAway(a_BlockType) && !IsBlockLiquid(a_BlockType))
+ {
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, (eBlockFace)a_EntryFace); // Was an unwashawayable block, can't overwrite it!
+ }
+ m_Pos.Set(a_BlockX, a_BlockY, a_BlockZ); // (Block could be washed away, replace it)
+ return true; // Abort tracing
+ }
+ return false;
+ }
+ } Callbacks;
+ cLineBlockTracer Tracer(*a_World, Callbacks);
+ Vector3d Start(a_Player->GetEyePosition());
+ Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
+
+ // cTracer::Trace returns true when whole line was traversed. By returning true when we hit something, we ensure that this never happens if liquid could be placed
+ // Use this to judge whether the position is valid
+ if (!Tracer.Trace(Start.x, Start.y, Start.z, End.x, End.y, End.z))
+ {
+ a_BlockPos = Callbacks.m_Pos;
+ a_BlockType = Callbacks.m_ReplacedBlock;
+ return true;
+ }
+
+ return false;
+ }
};
diff --git a/src/Items/ItemCake.h b/src/Items/ItemCake.h
index 48e23ed59..d1cb091b6 100644
--- a/src/Items/ItemCake.h
+++ b/src/Items/ItemCake.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemCauldron.h b/src/Items/ItemCauldron.h
index 07ae12660..9617c30ef 100644
--- a/src/Items/ItemCauldron.h
+++ b/src/Items/ItemCauldron.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemComparator.h b/src/Items/ItemComparator.h
index 60d9c3648..fc843c186 100644
--- a/src/Items/ItemComparator.h
+++ b/src/Items/ItemComparator.h
@@ -24,7 +24,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemDoor.h b/src/Items/ItemDoor.h
index f3677c28c..c1b439024 100644
--- a/src/Items/ItemDoor.h
+++ b/src/Items/ItemDoor.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
@@ -33,8 +33,8 @@ public:
a_BlockType = (m_ItemType == E_ITEM_WOODEN_DOOR) ? E_BLOCK_WOODEN_DOOR : E_BLOCK_IRON_DOOR;
cChunkInterface ChunkInterface(a_World->GetChunkMap());
bool Meta = BlockHandler(a_BlockType)->GetPlacementBlockTypeMeta(
- ChunkInterface, a_Player,
- a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
+ ChunkInterface, a_Player,
+ a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
a_CursorX, a_CursorY, a_CursorZ,
a_BlockType, a_BlockMeta
);
diff --git a/src/Items/ItemFishingRod.h b/src/Items/ItemFishingRod.h
index 0431b88b7..6350a38ba 100644
--- a/src/Items/ItemFishingRod.h
+++ b/src/Items/ItemFishingRod.h
@@ -17,13 +17,15 @@
-/////////////////////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////////////////
// cFloaterCallback
class cFloaterCallback :
public cEntityCallback
{
public:
- cFloaterCallback(void) :
+ cFloaterCallback(void) :
m_CanPickup(false),
m_AttachedMobID(-1)
{
@@ -49,14 +51,19 @@ protected:
Vector3d m_Pos;
} ;
-////////////////////////////////////////////////////////////////////////////
-// cSweepEntityCallback
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cSweepEntityCallback:
+
class cSweepEntityCallback :
public cEntityCallback
{
public:
cSweepEntityCallback(Vector3d a_PlayerPos) :
- m_PlayerPos(a_PlayerPos)
+ m_PlayerPos(a_PlayerPos)
{
}
@@ -73,6 +80,8 @@ protected:
+
+
class cItemFishingRodHandler :
public cItemHandler
{
@@ -106,19 +115,19 @@ public:
{
cItems Drops;
int ItemCategory = a_World->GetTickRandomNumber(99);
- if (ItemCategory <= 4) // Treasures 5%
+ if (ItemCategory <= 4) // Treasures 5%
{
int Treasure = a_World->GetTickRandomNumber(5);
switch (Treasure)
{
case 0:
{
- Drops.Add(cItem(E_ITEM_BOW)); // TODO: Enchantments
+ Drops.Add(cItem(E_ITEM_BOW)); // TODO: Enchantments
break;
}
case 1:
{
- Drops.Add(cItem(E_ITEM_BOOK)); // TODO: Enchanted book
+ Drops.Add(cItem(E_ITEM_BOOK)); // TODO: Enchanted book
break;
}
case 2:
@@ -142,6 +151,8 @@ public:
break;
}
}
+
+ a_Player->GetStatManager().AddValue(statTreasureFished, 1);
}
else if (ItemCategory <= 14) // Junk 10%
{
@@ -190,6 +201,8 @@ public:
{
Drops.Add(cItem(E_BLOCK_TRIPWIRE_HOOK));
}
+
+ a_Player->GetStatManager().AddValue(statJunkFished, 1);
}
else // Fish
{
@@ -197,7 +210,7 @@ public:
if (FishType <= 1) // Clownfish has a 2% chance of spawning
{
Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_CLOWNFISH));
- }
+ }
else if (FishType <= 12) // Pufferfish has a 13% chance of spawning
{
Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_CLOWNFISH));
@@ -210,6 +223,8 @@ public:
{
Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_FISH));
}
+
+ a_Player->GetStatManager().AddValue(statFishCaught, 1);
}
if (cRoot::Get()->GetPluginManager()->CallHookPlayerFishing(*a_Player, Drops))
@@ -225,9 +240,13 @@ public:
else
{
cFloater * Floater = new cFloater(a_Player->GetPosX(), a_Player->GetStance(), a_Player->GetPosZ(), a_Player->GetLookVector() * 15, a_Player->GetUniqueID(), 100 + a_World->GetTickRandomNumber(800) - (a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchLure) * 100));
- Floater->Initialize(a_World);
+ Floater->Initialize(*a_World);
a_Player->SetIsFishing(true, Floater->GetUniqueID());
}
return true;
}
} ;
+
+
+
+
diff --git a/src/Items/ItemFlowerPot.h b/src/Items/ItemFlowerPot.h
index 60bf87985..320dce997 100644
--- a/src/Items/ItemFlowerPot.h
+++ b/src/Items/ItemFlowerPot.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemFood.h b/src/Items/ItemFood.h
index 961cf482d..ff1d7991b 100644
--- a/src/Items/ItemFood.h
+++ b/src/Items/ItemFood.h
@@ -26,7 +26,7 @@ public:
virtual FoodInfo GetFoodInfo(void) override
{
- switch(m_ItemType)
+ switch (m_ItemType)
{
// Please keep alpha-sorted.
case E_ITEM_BAKED_POTATO: return FoodInfo(6, 7.2);
diff --git a/src/Items/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index ce9593a70..d36b5d663 100644
--- a/src/Items/ItemHandler.cpp
+++ b/src/Items/ItemHandler.cpp
@@ -19,6 +19,7 @@
#include "ItemCloth.h"
#include "ItemComparator.h"
#include "ItemDoor.h"
+#include "ItemMilk.h"
#include "ItemDye.h"
#include "ItemEmptyMap.h"
#include "ItemFishingRod.h"
@@ -34,6 +35,7 @@
#include "ItemNetherWart.h"
#include "ItemPainting.h"
#include "ItemPickaxe.h"
+#include "ItemPotion.h"
#include "ItemThrowable.h"
#include "ItemRedstoneDust.h"
#include "ItemRedstoneRepeater.h"
@@ -44,6 +46,7 @@
#include "ItemSign.h"
#include "ItemMobHead.h"
#include "ItemSpawnEgg.h"
+#include "ItemString.h"
#include "ItemSugarcane.h"
#include "ItemSword.h"
@@ -62,7 +65,7 @@ cItemHandler * cItemHandler::m_ItemHandler[2268];
cItemHandler * cItemHandler::GetItemHandler(int a_ItemType)
{
- if (a_ItemType < 0)
+ if ((a_ItemType < 0) || ((unsigned long)a_ItemType >= ARRAYCOUNT(m_ItemHandler)))
{
// Either nothing (-1), or bad value, both cases should return the air handler
if (a_ItemType < -1)
@@ -91,7 +94,7 @@ cItemHandler * cItemHandler::GetItemHandler(int a_ItemType)
cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
{
- switch(a_ItemType)
+ switch (a_ItemType)
{
default: return new cItemHandler(a_ItemType);
@@ -119,9 +122,11 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
case E_ITEM_FLOWER_POT: return new cItemFlowerPotHandler(a_ItemType);
case E_BLOCK_LILY_PAD: return new cItemLilypadHandler(a_ItemType);
case E_ITEM_MAP: return new cItemMapHandler();
+ case E_ITEM_MILK: return new cItemMilkHandler();
case E_ITEM_ITEM_FRAME: return new cItemItemFrameHandler(a_ItemType);
case E_ITEM_NETHER_WART: return new cItemNetherWartHandler(a_ItemType);
case E_ITEM_PAINTING: return new cItemPaintingHandler(a_ItemType);
+ case E_ITEM_POTIONS: return new cItemPotionHandler();
case E_ITEM_REDSTONE_DUST: return new cItemRedstoneDustHandler(a_ItemType);
case E_ITEM_REDSTONE_REPEATER: return new cItemRedstoneRepeaterHandler(a_ItemType);
case E_ITEM_SHEARS: return new cItemShearsHandler(a_ItemType);
@@ -129,6 +134,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:
@@ -257,9 +263,10 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
void cItemHandler::Deinit()
{
- for(int i = 0; i < 2267; i++)
+ for (int i = 0; i < 2267; i++)
{
delete m_ItemHandler[i];
+ m_ItemHandler[i] = NULL;
}
memset(m_ItemHandler, 0, sizeof(m_ItemHandler)); // Don't leave any dangling pointers around, just in case
m_HandlerInitialized = false;
@@ -321,15 +328,25 @@ void cItemHandler::OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const
if (a_Player->IsGameModeSurvival())
{
- if (!BlockRequiresSpecialTool(Block) || CanHarvestBlock(Block))
- {
- cChunkInterface ChunkInterface(a_World->GetChunkMap());
- cBlockInServerPluginInterface PluginInterface(*a_World);
- Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ);
- }
+ cChunkInterface ChunkInterface(a_World->GetChunkMap());
+ cBlockInServerPluginInterface PluginInterface(*a_World);
+ Handler->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, CanHarvestBlock(Block), a_Player->GetEquippedItem().m_Enchantments.GetLevel(cEnchantments::enchSilkTouch) > 0);
}
-
- a_Player->UseEquippedItem();
+
+ if (!cBlockInfo::IsOneHitDig(Block))
+ {
+ a_Player->UseEquippedItem(GetDurabilityLossByAction(dlaBreakBlock));
+ }
+}
+
+
+
+
+
+void cItemHandler::OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity)
+{
+ UNUSED(a_AttackedEntity);
+ a_Attacker->UseEquippedItem(GetDurabilityLossByAction(dlaAttackEntity));
}
@@ -347,6 +364,20 @@ void cItemHandler::OnFoodEaten(cWorld * a_World, cPlayer * a_Player, cItem * a_I
+short cItemHandler::GetDurabilityLossByAction(eDurabilityLostAction a_Action)
+{
+ switch ((int)a_Action)
+ {
+ case dlaAttackEntity: return 2;
+ case dlaBreakBlock: return 1;
+ }
+ return 0;
+}
+
+
+
+
+
char cItemHandler::GetMaxStackSize(void)
{
if (m_ItemType < 256)
@@ -355,7 +386,7 @@ char cItemHandler::GetMaxStackSize(void)
return 64;
}
- switch (m_ItemType) //sorted by id
+ switch (m_ItemType)
{
case E_ITEM_ARROW: return 64;
case E_ITEM_BAKED_POTATO: return 64;
@@ -451,14 +482,14 @@ char cItemHandler::GetMaxStackSize(void)
bool cItemHandler::IsTool()
{
// TODO: Rewrite this to list all tools specifically
- return
- (m_ItemType >= 256 && m_ItemType <= 259)
- || (m_ItemType == 261)
- || (m_ItemType >= 267 && m_ItemType <= 279)
- || (m_ItemType >= 283 && m_ItemType <= 286)
- || (m_ItemType >= 290 && m_ItemType <= 294)
- || (m_ItemType == 325)
- || (m_ItemType == 346);
+ return
+ ((m_ItemType >= 256) && (m_ItemType <= 259)) ||
+ (m_ItemType == 261) ||
+ ((m_ItemType >= 267) && (m_ItemType <= 279)) ||
+ ((m_ItemType >= 283) && (m_ItemType <= 286)) ||
+ ((m_ItemType >= 290) && (m_ItemType <= 294)) ||
+ (m_ItemType == 325) ||
+ (m_ItemType == 346);
}
@@ -467,33 +498,17 @@ bool cItemHandler::IsTool()
bool cItemHandler::IsFood(void)
{
- switch (m_ItemType)
- {
- case E_ITEM_RED_APPLE:
- case E_ITEM_GOLDEN_APPLE:
- case E_ITEM_MUSHROOM_SOUP:
- case E_ITEM_BREAD:
- case E_ITEM_RAW_PORKCHOP:
- case E_ITEM_COOKED_PORKCHOP:
- case E_ITEM_MILK:
- case E_ITEM_RAW_FISH:
- case E_ITEM_COOKED_FISH:
- case E_ITEM_COOKIE:
- case E_ITEM_MELON_SLICE:
- case E_ITEM_RAW_BEEF:
- case E_ITEM_STEAK:
- case E_ITEM_RAW_CHICKEN:
- case E_ITEM_COOKED_CHICKEN:
- case E_ITEM_ROTTEN_FLESH:
- case E_ITEM_SPIDER_EYE:
- case E_ITEM_CARROT:
- case E_ITEM_POTATO:
- case E_ITEM_BAKED_POTATO:
- case E_ITEM_POISONOUS_POTATO:
- {
- return true;
- }
- } // switch (m_ItemType)
+ return false;
+}
+
+
+
+
+
+bool cItemHandler::IsDrinkable(short a_ItemDamage)
+{
+ UNUSED(a_ItemDamage);
+
return false;
}
@@ -511,10 +526,10 @@ bool cItemHandler::IsPlaceable(void)
-bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
+
+bool cItemHandler::CanRepairWithRawMaterial(short a_ItemType)
{
- UNUSED(a_BlockType);
-
+ UNUSED(a_ItemType);
return false;
}
@@ -522,9 +537,61 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
+bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
+{
+ switch (a_BlockType)
+ {
+ case E_BLOCK_ANVIL:
+ case E_BLOCK_ENCHANTMENT_TABLE:
+ case E_BLOCK_FURNACE:
+ case E_BLOCK_LIT_FURNACE:
+ case E_BLOCK_COAL_ORE:
+ case E_BLOCK_STONE:
+ case E_BLOCK_COBBLESTONE:
+ case E_BLOCK_END_STONE:
+ case E_BLOCK_MOSSY_COBBLESTONE:
+ case E_BLOCK_SANDSTONE_STAIRS:
+ case E_BLOCK_SANDSTONE:
+ case E_BLOCK_STONE_BRICKS:
+ case E_BLOCK_NETHER_BRICK:
+ case E_BLOCK_NETHERRACK:
+ case E_BLOCK_STONE_SLAB:
+ case E_BLOCK_DOUBLE_STONE_SLAB:
+ case E_BLOCK_STONE_PRESSURE_PLATE:
+ case E_BLOCK_BRICK:
+ case E_BLOCK_COBBLESTONE_STAIRS:
+ case E_BLOCK_COBBLESTONE_WALL:
+ case E_BLOCK_STONE_BRICK_STAIRS:
+ case E_BLOCK_NETHER_BRICK_STAIRS:
+ case E_BLOCK_CAULDRON:
+ case E_BLOCK_OBSIDIAN:
+ case E_BLOCK_DIAMOND_BLOCK:
+ case E_BLOCK_DIAMOND_ORE:
+ case E_BLOCK_GOLD_BLOCK:
+ case E_BLOCK_GOLD_ORE:
+ case E_BLOCK_REDSTONE_ORE:
+ case E_BLOCK_REDSTONE_ORE_GLOWING:
+ case E_BLOCK_EMERALD_ORE:
+ case E_BLOCK_IRON_BLOCK:
+ case E_BLOCK_IRON_ORE:
+ case E_BLOCK_LAPIS_ORE:
+ case E_BLOCK_LAPIS_BLOCK:
+ case E_BLOCK_SNOW:
+ case E_BLOCK_VINES:
+ {
+ return false;
+ }
+ default: return true;
+ }
+}
+
+
+
+
+
bool cItemHandler::GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
)
@@ -541,7 +608,7 @@ bool cItemHandler::GetPlacementBlockTypeMeta(
cChunkInterface ChunkInterface(a_World->GetChunkMap());
return BlockH->GetPlacementBlockTypeMeta(
ChunkInterface, a_Player,
- a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
+ a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
a_CursorX, a_CursorY, a_CursorZ,
a_BlockType, a_BlockMeta
);
@@ -567,7 +634,7 @@ bool cItemHandler::EatItem(cPlayer * a_Player, cItem * a_Item)
cFastRandom r1;
if ((r1.NextInt(100, a_Player->GetUniqueID()) - Info.PoisonChance) <= 0)
{
- a_Player->FoodPoison(300);
+ a_Player->FoodPoison(600); // Give the player food poisoning for 30 seconds.
}
}
diff --git a/src/Items/ItemHandler.h b/src/Items/ItemHandler.h
index 4993eac85..1d5f59f3e 100644
--- a/src/Items/ItemHandler.h
+++ b/src/Items/ItemHandler.h
@@ -19,6 +19,13 @@ class cPlayer;
class cItemHandler
{
public:
+
+ enum eDurabilityLostAction
+ {
+ dlaBreakBlock,
+ dlaAttackEntity,
+ };
+
cItemHandler(int a_ItemType);
/** Force virtual destructor */
@@ -28,7 +35,7 @@ public:
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir);
/** Called when the client sends the SHOOT status in the lclk packet */
- virtual void OnItemShoot(cPlayer *, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
+ virtual void OnItemShoot(cPlayer *, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace)
{
UNUSED(a_BlockX);
UNUSED(a_BlockY);
@@ -48,11 +55,17 @@ public:
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace);
/** Called when the player destroys a block using this item. This also calls the drop function for the destroyed block */
- virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_X, int a_Y, int a_Z);
+ virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ);
+
+ /** Called when a player attacks a other entity. */
+ virtual void OnEntityAttack(cPlayer * a_Attacker, cEntity * a_AttackedEntity);
/** Called after the player has eaten this item. */
virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item);
-
+
+ /** Get the durability lost which the item will get, when a specified action was performed. */
+ virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action);
+
/** Returns the maximum stack size for a given item */
virtual char GetMaxStackSize(void);
@@ -60,7 +73,7 @@ public:
{
double Saturation;
int FoodLevel;
- int PoisonChance; // 0 - 100, in percent. 0 = no chance of poisoning, 100 = sure poisoning
+ int PoisonChance; // 0 - 100, in percent. 0 = no chance of poisoning, 100 = sure poisoning
FoodInfo(int a_FoodLevel, double a_Saturation, int a_PoisonChance = 0) :
Saturation(a_Saturation),
@@ -82,21 +95,27 @@ public:
/** Indicates if this item is food */
virtual bool IsFood(void);
+ /** Indicates if this item is drinkable */
+ virtual bool IsDrinkable(short a_ItemDamage);
+
/** Blocks simply get placed */
virtual bool IsPlaceable(void);
- /** Called before a block is placed into a world.
+ /** Can the anvil repair this item, when a_Item is the second input? */
+ virtual bool CanRepairWithRawMaterial(short a_ItemType);
+
+ /** Called before a block is placed into a world.
The handler should return true to allow placement, false to refuse.
Also, the handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block.
*/
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
);
- /** Returns whether this tool/item can harvest a specific block (e.g. wooden pickaxe can harvest stone, but wood can�t) DEFAULT: False */
+ /** Returns whether this tool/item can harvest a specific block (e.g. wooden pickaxe can harvest stone, but wood can't) DEFAULT: False */
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType);
static cItemHandler * GetItemHandler(int a_ItemType);
@@ -106,11 +125,11 @@ public:
protected:
int m_ItemType;
- static cItemHandler *CreateItemHandler(int m_ItemType);
+ static cItemHandler * CreateItemHandler(int m_ItemType);
static cItemHandler * m_ItemHandler[E_ITEM_LAST + 1];
- static bool m_HandlerInitialized; //used to detect if the itemhandlers are initialized
+ static bool m_HandlerInitialized; // used to detect if the itemhandlers are initialized
};
-//Short function
+// Short function
inline cItemHandler *ItemHandler(int a_ItemType) { return cItemHandler::GetItemHandler(a_ItemType); }
diff --git a/src/Items/ItemHoe.h b/src/Items/ItemHoe.h
index 29f7c83d5..8d0b71478 100644
--- a/src/Items/ItemHoe.h
+++ b/src/Items/ItemHoe.h
@@ -16,7 +16,6 @@ public:
cItemHoeHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
-
}
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
@@ -26,13 +25,18 @@ public:
if ((Block == E_BLOCK_DIRT) || (Block == E_BLOCK_GRASS))
{
a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FARMLAND, 0);
-
a_Player->UseEquippedItem();
return true;
-
}
+
return false;
}
+
+
+ virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override
+ {
+ return 0;
+ }
} ;
diff --git a/src/Items/ItemItemFrame.h b/src/Items/ItemItemFrame.h
index 27e7dba35..87e20ecf0 100644
--- a/src/Items/ItemItemFrame.h
+++ b/src/Items/ItemItemFrame.h
@@ -27,16 +27,17 @@ public:
return false;
}
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again
if (Block == E_BLOCK_AIR)
{
cItemFrame * ItemFrame = new cItemFrame(a_Dir, a_BlockX, a_BlockY, a_BlockZ);
- if (!ItemFrame->Initialize(a_World))
+ if (!ItemFrame->Initialize(*a_World))
{
delete ItemFrame;
+ ItemFrame = NULL;
return false;
}
diff --git a/src/Items/ItemLeaves.h b/src/Items/ItemLeaves.h
index 12cb45d1c..f48126dc5 100644
--- a/src/Items/ItemLeaves.h
+++ b/src/Items/ItemLeaves.h
@@ -20,7 +20,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
@@ -31,7 +31,7 @@ public:
a_CursorX, a_CursorY, a_CursorZ,
a_BlockType, a_BlockMeta
);
- a_BlockMeta = a_BlockMeta | 0x4; //0x4 bit set means this is a player-placed leaves block, not to be decayed
+ a_BlockMeta = a_BlockMeta | 0x4; // 0x4 bit set means this is a player-placed leaves block, not to be decayed
return res;
}
} ;
diff --git a/src/Items/ItemLighter.h b/src/Items/ItemLighter.h
index 32f49cab6..9f98bf85f 100644
--- a/src/Items/ItemLighter.h
+++ b/src/Items/ItemLighter.h
@@ -52,8 +52,8 @@ public:
case E_BLOCK_TNT:
{
// Activate the TNT:
- a_World->BroadcastSoundEffect("game.tnt.primed", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 1.0f);
- a_World->SetBlock(a_BlockX,a_BlockY,a_BlockZ, E_BLOCK_AIR, 0);
+ a_World->BroadcastSoundEffect("game.tnt.primed", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0f, 1.0f);
+ a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_World->SpawnPrimedTNT(a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5); // 80 ticks to boom
break;
}
@@ -68,7 +68,7 @@ public:
if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) == E_BLOCK_AIR)
{
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0);
- a_World->BroadcastSoundEffect("fire.ignite", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0F, 1.04F);
+ a_World->BroadcastSoundEffect("fire.ignite", (double)a_BlockX, (double)a_BlockY, (double)a_BlockZ, 1.0F, 1.04F);
break;
}
}
diff --git a/src/Items/ItemLilypad.h b/src/Items/ItemLilypad.h
index 8fc1d8543..b9d837384 100644
--- a/src/Items/ItemLilypad.h
+++ b/src/Items/ItemLilypad.h
@@ -25,7 +25,7 @@ public:
virtual bool IsPlaceable(void) override
{
- return false; // Set as not placeable so OnItemUse is called
+ return false; // Set as not placeable so OnItemUse is called
}
@@ -47,9 +47,9 @@ public:
public cBlockTracer::cCallbacks
{
public:
- cCallbacks(cWorld * a_CBWorld) :
- m_HasHitFluid(false),
- m_World(a_CBWorld)
+
+ cCallbacks(void) :
+ m_HasHitFluid(false)
{
}
@@ -57,15 +57,14 @@ public:
{
if (IsBlockWater(a_CBBlockType))
{
- if ((a_CBBlockMeta != 0) || (a_CBEntryFace == BLOCK_FACE_NONE)) // The hit block should be a source. The FACE_NONE check is clicking whilst submerged
+ if ((a_CBBlockMeta != 0) || (a_CBEntryFace == BLOCK_FACE_NONE)) // The hit block should be a source. The FACE_NONE check is clicking whilst submerged
{
return false;
}
AddFaceDirection(a_CBBlockX, a_CBBlockY, a_CBBlockZ, BLOCK_FACE_YP); // Always place pad at top of water block
- BLOCKTYPE Block = m_World->GetBlock(a_CBBlockX, a_CBBlockY, a_CBBlockZ);
if (
- !IsBlockWater(Block) &&
- cBlockInfo::FullyOccupiesVoxel(Block)
+ !IsBlockWater(a_CBBlockType) &&
+ cBlockInfo::FullyOccupiesVoxel(a_CBBlockType)
)
{
// Can't place lilypad on air/in another block!
@@ -80,11 +79,10 @@ public:
Vector3i m_Pos;
bool m_HasHitFluid;
- cWorld * m_World;
};
- cCallbacks Callbacks(a_World);
+ cCallbacks Callbacks;
cLineBlockTracer Tracer(*a_Player->GetWorld(), Callbacks);
Vector3d Start(a_Player->GetEyePosition() + a_Player->GetLookVector());
Vector3d End(a_Player->GetEyePosition() + a_Player->GetLookVector() * 5);
diff --git a/src/Items/ItemMilk.h b/src/Items/ItemMilk.h
new file mode 100644
index 000000000..db7bc13be
--- /dev/null
+++ b/src/Items/ItemMilk.h
@@ -0,0 +1,28 @@
+
+#pragma once
+
+class cItemMilkHandler:
+ public cItemHandler
+{
+ typedef cItemHandler super;
+public:
+ cItemMilkHandler():
+ super(E_ITEM_MILK)
+ {
+ }
+
+ virtual bool IsDrinkable(short a_ItemDamage) override
+ {
+ UNUSED(a_ItemDamage);
+ return true;
+ }
+
+ virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) override
+ {
+ UNUSED(a_Item);
+ a_Player->ClearEntityEffects();
+ a_Player->GetInventory().RemoveOneEquippedItem();
+ a_Player->GetInventory().AddItem(E_ITEM_BUCKET);
+ return true;
+ }
+};
diff --git a/src/Items/ItemMinecart.h b/src/Items/ItemMinecart.h
index 25500aeb9..63038de51 100644
--- a/src/Items/ItemMinecart.h
+++ b/src/Items/ItemMinecart.h
@@ -70,7 +70,7 @@ public:
return false;
}
} // switch (m_ItemType)
- Minecart->Initialize(a_World);
+ Minecart->Initialize(*a_World);
if (!a_Player->IsGameModeCreative())
{
@@ -78,7 +78,7 @@ public:
}
return true;
}
-
+
} ;
diff --git a/src/Items/ItemMobHead.h b/src/Items/ItemMobHead.h
index 5ae040282..4c36fe8d8 100644
--- a/src/Items/ItemMobHead.h
+++ b/src/Items/ItemMobHead.h
@@ -26,7 +26,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemNetherWart.h b/src/Items/ItemNetherWart.h
index a6a9a286a..10a0864b5 100644
--- a/src/Items/ItemNetherWart.h
+++ b/src/Items/ItemNetherWart.h
@@ -25,7 +25,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemPainting.h b/src/Items/ItemPainting.h
index b85098221..a2a77ce21 100644
--- a/src/Items/ItemPainting.h
+++ b/src/Items/ItemPainting.h
@@ -27,9 +27,9 @@ public:
return false;
}
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); // Make sure block that will be occupied is free
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
- AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again
+ AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir, true); // We want the clicked block, so go back again
if (Block == E_BLOCK_AIR)
{
@@ -38,14 +38,14 @@ public:
// The client uses different values for painting directions and block faces. Our constants are for the block faces, so we convert them here to painting faces
switch (a_Dir)
{
- case BLOCK_FACE_ZP: break; // Initialised to zero
+ case BLOCK_FACE_ZP: break; // Initialised to zero
case BLOCK_FACE_ZM: Dir = 2; break;
case BLOCK_FACE_XM: Dir = 1; break;
case BLOCK_FACE_XP: Dir = 3; break;
default: ASSERT(!"Unhandled block face when trying spawn painting!"); return false;
}
- static const struct // Define all the possible painting titles
+ static const struct // Define all the possible painting titles
{
AString Title;
} gPaintingTitlesList[] =
@@ -79,7 +79,7 @@ public:
};
cPainting * Painting = new cPainting(gPaintingTitlesList[a_World->GetTickRandomNumber(ARRAYCOUNT(gPaintingTitlesList) - 1)].Title, Dir, a_BlockX, a_BlockY, a_BlockZ);
- Painting->Initialize(a_World);
+ Painting->Initialize(*a_World);
if (!a_Player->IsGameModeCreative())
{
diff --git a/src/Items/ItemPickaxe.h b/src/Items/ItemPickaxe.h
index 2a8e40daa..17fd96822 100644
--- a/src/Items/ItemPickaxe.h
+++ b/src/Items/ItemPickaxe.h
@@ -8,6 +8,7 @@
class cItemPickaxeHandler :
public cItemHandler
{
+ typedef cItemHandler super;
public:
cItemPickaxeHandler(int a_ItemType)
: cItemHandler(a_ItemType)
@@ -17,7 +18,7 @@ public:
char PickaxeLevel()
{
- switch(m_ItemType)
+ switch (m_ItemType)
{
case E_ITEM_WOODEN_PICKAXE: return 1;
case E_ITEM_GOLD_PICKAXE: return 1;
@@ -31,7 +32,7 @@ public:
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) override
{
- switch(a_BlockType)
+ switch (a_BlockType)
{
case E_BLOCK_OBSIDIAN:
{
@@ -76,6 +77,7 @@ public:
case E_BLOCK_STONE_PRESSURE_PLATE:
case E_BLOCK_BRICK:
case E_BLOCK_COBBLESTONE_STAIRS:
+ case E_BLOCK_COBBLESTONE_WALL:
case E_BLOCK_STONE_BRICK_STAIRS:
case E_BLOCK_NETHER_BRICK_STAIRS:
case E_BLOCK_CAULDRON:
@@ -83,6 +85,19 @@ public:
return PickaxeLevel() >= 1;
}
}
+ return super::CanHarvestBlock(a_BlockType);
+ }
+
+ virtual bool CanRepairWithRawMaterial(short a_ItemType) override
+ {
+ switch (m_ItemType)
+ {
+ case E_ITEM_WOODEN_PICKAXE: return (a_ItemType == E_BLOCK_PLANKS);
+ case E_ITEM_STONE_PICKAXE: return (a_ItemType == E_BLOCK_COBBLESTONE);
+ case E_ITEM_IRON_PICKAXE: return (a_ItemType == E_ITEM_IRON);
+ case E_ITEM_GOLD_PICKAXE: return (a_ItemType == E_ITEM_GOLD);
+ case E_ITEM_DIAMOND_PICKAXE: return (a_ItemType == E_ITEM_DIAMOND);
+ }
return false;
}
} ;
diff --git a/src/Items/ItemPotion.h b/src/Items/ItemPotion.h
new file mode 100644
index 000000000..24614cd8a
--- /dev/null
+++ b/src/Items/ItemPotion.h
@@ -0,0 +1,79 @@
+
+#pragma once
+
+#include "../Entities/EntityEffect.h"
+#include "../Entities/SplashPotionEntity.h"
+
+class cItemPotionHandler:
+ public cItemHandler
+{
+ typedef cItemHandler super;
+
+public:
+
+ cItemPotionHandler():
+ super(E_ITEM_POTION)
+ {
+ }
+
+
+ // cItemHandler overrides:
+ virtual bool IsDrinkable(short a_ItemDamage) override
+ {
+ // Drinkable potion if 13th lowest bit is set
+ // Ref.: http://minecraft.gamepedia.com/Potions#Data_value_table
+ return cEntityEffect::IsPotionDrinkable(a_ItemDamage);
+ }
+
+
+ virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
+ {
+ short PotionDamage = a_Item.m_ItemDamage;
+
+ // Do not throw non-splash potions:
+ if (cEntityEffect::IsPotionDrinkable(PotionDamage))
+ {
+ return false;
+ }
+
+ Vector3d Pos = a_Player->GetThrowStartPos();
+ Vector3d Speed = a_Player->GetLookVector() * 7;
+
+ if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity::pkSplashPotion, a_Player, &a_Player->GetEquippedItem(), &Speed) < 0)
+ {
+ return false;
+ }
+
+ if (!a_Player->IsGameModeCreative())
+ {
+ a_Player->GetInventory().RemoveOneEquippedItem();
+ }
+
+ return true;
+ }
+
+
+ virtual bool EatItem(cPlayer * a_Player, cItem * a_Item) override
+ {
+ short PotionDamage = a_Item->m_ItemDamage;
+
+ // Do not drink undrinkable potions:
+ if (!cEntityEffect::IsPotionDrinkable(a_Item->m_ItemDamage))
+ {
+ return false;
+ }
+
+ a_Player->AddEntityEffect(
+ cEntityEffect::GetPotionEffectType(PotionDamage),
+ cEntityEffect::GetPotionEffectDuration(PotionDamage),
+ cEntityEffect::GetPotionEffectIntensity(PotionDamage)
+ );
+ a_Player->GetInventory().RemoveOneEquippedItem();
+ a_Player->GetInventory().AddItem(E_ITEM_GLASS_BOTTLE);
+ return true;
+ }
+};
+
+
+
+
diff --git a/src/Items/ItemRedstoneDust.h b/src/Items/ItemRedstoneDust.h
index 274d905a5..a2289239c 100644
--- a/src/Items/ItemRedstoneDust.h
+++ b/src/Items/ItemRedstoneDust.h
@@ -22,12 +22,12 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
{
- if (!cBlockInfo::FullyOccupiesVoxel(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))) // Some solid blocks, such as cocoa beans, are not suitable for dust
+ if (!cBlockInfo::FullyOccupiesVoxel(a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))) // Some solid blocks, such as cocoa beans, are not suitable for dust
{
return false;
}
diff --git a/src/Items/ItemRedstoneRepeater.h b/src/Items/ItemRedstoneRepeater.h
index c5fb5d566..13a797d00 100644
--- a/src/Items/ItemRedstoneRepeater.h
+++ b/src/Items/ItemRedstoneRepeater.h
@@ -24,7 +24,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemSapling.h b/src/Items/ItemSapling.h
index 61b1a32be..dbcb12be5 100644
--- a/src/Items/ItemSapling.h
+++ b/src/Items/ItemSapling.h
@@ -20,7 +20,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemSeeds.h b/src/Items/ItemSeeds.h
index 7283edcee..54a1183d7 100644
--- a/src/Items/ItemSeeds.h
+++ b/src/Items/ItemSeeds.h
@@ -25,12 +25,12 @@ public:
virtual bool IsFood(void) override
{
- switch (m_ItemType) // Special cases, both a seed and food
+ switch (m_ItemType) // Special cases, both a seed and food
{
case E_ITEM_CARROT:
case E_ITEM_POTATO: return true;
default: return false;
- }
+ }
}
virtual FoodInfo GetFoodInfo(void) override
@@ -40,12 +40,12 @@ public:
case E_ITEM_CARROT: return FoodInfo(4, 4.8);
case E_ITEM_POTATO: return FoodInfo(1, 0.6);
default: return FoodInfo(0, 0);
- }
+ }
}
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemShears.h b/src/Items/ItemShears.h
index 39d2776fa..fa2794df2 100644
--- a/src/Items/ItemShears.h
+++ b/src/Items/ItemShears.h
@@ -12,6 +12,7 @@
class cItemShearsHandler :
public cItemHandler
{
+ typedef cItemHandler super;
public:
cItemShearsHandler(int a_ItemType) :
cItemHandler(a_ItemType)
@@ -30,8 +31,12 @@ public:
BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if ((Block == E_BLOCK_LEAVES) || (Block == E_BLOCK_NEW_LEAVES))
{
+ NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
+ cBlockHandler * Handler = cBlockInfo::GetHandler(Block);
+
cItems Drops;
- Drops.push_back(cItem(Block, 1, a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) & 0x03));
+ Handler->ConvertToPickups(Drops, Meta);
+ Drops.push_back(cItem(Block, 1, Meta & 3));
a_World->SpawnItemPickups(Drops, a_BlockX, a_BlockY, a_BlockZ);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
@@ -54,7 +59,25 @@ public:
return true;
}
} // switch (a_BlockType)
- return false;
+ return super::CanHarvestBlock(a_BlockType);
+ }
+
+
+ virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override
+ {
+ return 0;
+ }
+
+
+ virtual void OnBlockDestroyed(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ) override
+ {
+ super::OnBlockDestroyed(a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ);
+
+ BLOCKTYPE Block = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
+ if ((Block == E_BLOCK_TRIPWIRE) || (Block == E_BLOCK_VINES))
+ {
+ a_Player->UseEquippedItem();
+ }
}
} ;
diff --git a/src/Items/ItemShovel.h b/src/Items/ItemShovel.h
index 873d5ae25..7d5760fa9 100644
--- a/src/Items/ItemShovel.h
+++ b/src/Items/ItemShovel.h
@@ -14,6 +14,7 @@
class cItemShovelHandler : public cItemHandler
{
+ typedef cItemHandler super;
public:
cItemShovelHandler(int a_ItemType)
: cItemHandler(a_ItemType)
@@ -28,7 +29,7 @@ public:
{
cChunkInterface ChunkInterface(a_World->GetChunkMap());
cBlockInServerPluginInterface PluginInterface(*a_World);
- BlockHandler(Block)->DropBlock(ChunkInterface,*a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ);
+ BlockHandler(Block)->DropBlock(ChunkInterface, *a_World, PluginInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
a_Player->UseEquippedItem();
@@ -39,6 +40,24 @@ public:
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) override
{
- return (a_BlockType == E_BLOCK_SNOW);
+ if (a_BlockType == E_BLOCK_SNOW)
+ {
+ return true;
+ }
+ return super::CanHarvestBlock(a_BlockType);
+ }
+
+ virtual bool CanRepairWithRawMaterial(short a_ItemType) override
+ {
+ switch (m_ItemType)
+ {
+ case E_ITEM_WOODEN_SHOVEL: return (a_ItemType == E_BLOCK_PLANKS);
+ case E_ITEM_STONE_SHOVEL: return (a_ItemType == E_BLOCK_COBBLESTONE);
+ case E_ITEM_IRON_SHOVEL: return (a_ItemType == E_ITEM_IRON);
+ case E_ITEM_GOLD_SHOVEL: return (a_ItemType == E_ITEM_GOLD);
+ case E_ITEM_DIAMOND_SHOVEL: return (a_ItemType == E_ITEM_DIAMOND);
+ }
+ return false;
}
+
};
diff --git a/src/Items/ItemSign.h b/src/Items/ItemSign.h
index 60cf0f5f8..0fa0fa0be 100644
--- a/src/Items/ItemSign.h
+++ b/src/Items/ItemSign.h
@@ -3,7 +3,8 @@
#include "ItemHandler.h"
#include "../World.h"
-#include "../Blocks/BlockSign.h"
+#include "../Blocks/BlockSignPost.h"
+#include "../Blocks/BlockWallSign.h"
@@ -27,19 +28,19 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
{
if (a_BlockFace == BLOCK_FACE_TOP)
{
- a_BlockMeta = cBlockSignHandler::RotationToMetaData(a_Player->GetYaw());
+ a_BlockMeta = cBlockSignPostHandler::RotationToMetaData(a_Player->GetYaw());
a_BlockType = E_BLOCK_SIGN_POST;
}
else
{
- a_BlockMeta = cBlockSignHandler::DirectionToMetaData(a_BlockFace);
+ a_BlockMeta = cBlockWallSignHandler::DirectionToMetaData(a_BlockFace);
a_BlockType = E_BLOCK_WALLSIGN;
}
return true;
diff --git a/src/Items/ItemSpawnEgg.h b/src/Items/ItemSpawnEgg.h
index 0d6019398..bba97afa1 100644
--- a/src/Items/ItemSpawnEgg.h
+++ b/src/Items/ItemSpawnEgg.h
@@ -33,7 +33,10 @@ public:
a_BlockY--;
}
- if (a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, (cMonster::eType)(a_Item.m_ItemDamage)) >= 0)
+ cMonster::eType MonsterType = ItemDamageToMonsterType(a_Item.m_ItemDamage);
+ if (
+ (MonsterType != cMonster::mtInvalidType) && // Valid monster type
+ (a_World->SpawnMob(a_BlockX + 0.5, a_BlockY, a_BlockZ + 0.5, MonsterType) >= 0)) // Spawning succeeded
{
if (!a_Player->IsGameModeCreative())
{
@@ -45,6 +48,41 @@ public:
return false;
}
+
+
+ /** Converts the Spawn egg item damage to the monster type to spawn.
+ Returns mtInvalidType for invalid damage values. */
+ static cMonster::eType ItemDamageToMonsterType(short a_ItemDamage)
+ {
+ switch (a_ItemDamage)
+ {
+ case E_META_SPAWN_EGG_BAT: return cMonster::mtBat;
+ case E_META_SPAWN_EGG_BLAZE: return cMonster::mtBlaze;
+ case E_META_SPAWN_EGG_CAVE_SPIDER: return cMonster::mtCaveSpider;
+ case E_META_SPAWN_EGG_CHICKEN: return cMonster::mtChicken;
+ case E_META_SPAWN_EGG_COW: return cMonster::mtCow;
+ case E_META_SPAWN_EGG_CREEPER: return cMonster::mtCreeper;
+ case E_META_SPAWN_EGG_ENDERMAN: return cMonster::mtEnderman;
+ case E_META_SPAWN_EGG_GHAST: return cMonster::mtGhast;
+ case E_META_SPAWN_EGG_HORSE: return cMonster::mtHorse;
+ case E_META_SPAWN_EGG_MAGMA_CUBE: return cMonster::mtMagmaCube;
+ case E_META_SPAWN_EGG_MOOSHROOM: return cMonster::mtMooshroom;
+ case E_META_SPAWN_EGG_OCELOT: return cMonster::mtOcelot;
+ case E_META_SPAWN_EGG_PIG: return cMonster::mtPig;
+ case E_META_SPAWN_EGG_SHEEP: return cMonster::mtSheep;
+ case E_META_SPAWN_EGG_SILVERFISH: return cMonster::mtSilverfish;
+ case E_META_SPAWN_EGG_SKELETON: return cMonster::mtSkeleton;
+ case E_META_SPAWN_EGG_SLIME: return cMonster::mtSlime;
+ case E_META_SPAWN_EGG_SPIDER: return cMonster::mtSpider;
+ case E_META_SPAWN_EGG_SQUID: return cMonster::mtSquid;
+ case E_META_SPAWN_EGG_VILLAGER: return cMonster::mtVillager;
+ case E_META_SPAWN_EGG_WITCH: return cMonster::mtWitch;
+ case E_META_SPAWN_EGG_WOLF: return cMonster::mtWolf;
+ case E_META_SPAWN_EGG_ZOMBIE: return cMonster::mtZombie;
+ case E_META_SPAWN_EGG_ZOMBIE_PIGMAN: return cMonster::mtZombiePigman;
+ }
+ return cMonster::mtInvalidType;
+ }
} ;
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/Items/ItemSugarcane.h b/src/Items/ItemSugarcane.h
index e891cc367..dd2e2ece3 100644
--- a/src/Items/ItemSugarcane.h
+++ b/src/Items/ItemSugarcane.h
@@ -23,7 +23,7 @@ public:
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
- int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
+ 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
diff --git a/src/Items/ItemSword.h b/src/Items/ItemSword.h
index a7c1d2432..2b2dbfc0d 100644
--- a/src/Items/ItemSword.h
+++ b/src/Items/ItemSword.h
@@ -12,16 +12,46 @@
class cItemSwordHandler :
public cItemHandler
{
+ typedef cItemHandler super;
public:
cItemSwordHandler(int a_ItemType)
: cItemHandler(a_ItemType)
{
-
}
-
+
+
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType) override
{
- return (a_BlockType == E_BLOCK_COBWEB);
+ if (a_BlockType == E_BLOCK_COBWEB)
+ {
+ return true;
+ }
+ return super::CanHarvestBlock(a_BlockType);
+ }
+
+
+ virtual bool CanRepairWithRawMaterial(short a_ItemType) override
+ {
+ switch (m_ItemType)
+ {
+ case E_ITEM_WOODEN_SWORD: return (a_ItemType == E_BLOCK_PLANKS);
+ case E_ITEM_STONE_SWORD: return (a_ItemType == E_BLOCK_COBBLESTONE);
+ case E_ITEM_IRON_SWORD: return (a_ItemType == E_ITEM_IRON);
+ case E_ITEM_GOLD_SWORD: return (a_ItemType == E_ITEM_GOLD);
+ case E_ITEM_DIAMOND_SWORD: return (a_ItemType == E_ITEM_DIAMOND);
+ }
+ return false;
+ }
+
+
+ virtual short GetDurabilityLossByAction(eDurabilityLostAction a_Action) override
+ {
+ switch ((int)a_Action)
+ {
+ case dlaAttackEntity: return 1;
+ case dlaBreakBlock: return 2;
+ }
+ return 0;
}
} ;
diff --git a/src/Items/ItemThrowable.h b/src/Items/ItemThrowable.h
index c6a4e714e..c151c5d3a 100644
--- a/src/Items/ItemThrowable.h
+++ b/src/Items/ItemThrowable.h
@@ -28,15 +28,23 @@ public:
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_Dir) override
{
+ Vector3d Pos = a_Player->GetThrowStartPos();
+ Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
+
+ // Play sound
+ cFastRandom Random;
+ a_World->BroadcastSoundEffect("random.bow", a_Player->GetPosX(), a_Player->GetPosY() - a_Player->GetHeight(), a_Player->GetPosZ(), 0.5f, 0.4f / (Random.NextFloat(1.0f) * 0.4f + 0.8f));
+
+ if (a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem(), &Speed) < 0)
+ {
+ return false;
+ }
+
if (!a_Player->IsGameModeCreative())
{
a_Player->GetInventory().RemoveOneEquippedItem();
}
- Vector3d Pos = a_Player->GetThrowStartPos();
- Vector3d Speed = a_Player->GetLookVector() * m_SpeedCoeff;
- a_World->CreateProjectile(Pos.x, Pos.y, Pos.z, m_ProjectileKind, a_Player, a_Player->GetEquippedItem(), &Speed);
-
return true;
}
@@ -127,7 +135,10 @@ public:
return false;
}
- a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem());
+ if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, &a_Player->GetEquippedItem()) < 0)
+ {
+ return false;
+ }
if (!a_Player->IsGameModeCreative())
{