summaryrefslogtreecommitdiffstats
path: root/src/Items
diff options
context:
space:
mode:
Diffstat (limited to 'src/Items')
-rw-r--r--src/Items/ItemBed.h2
-rw-r--r--src/Items/ItemBow.h16
-rw-r--r--src/Items/ItemBrewingStand.h2
-rw-r--r--src/Items/ItemBucket.h79
-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.h31
-rw-r--r--src/Items/ItemFlowerPot.h2
-rw-r--r--src/Items/ItemHandler.cpp70
-rw-r--r--src/Items/ItemHandler.h19
-rw-r--r--src/Items/ItemItemFrame.h4
-rw-r--r--src/Items/ItemLeaves.h4
-rw-r--r--src/Items/ItemLighter.h6
-rw-r--r--src/Items/ItemLilypad.h4
-rw-r--r--src/Items/ItemMilk.h28
-rw-r--r--src/Items/ItemMobHead.h2
-rw-r--r--src/Items/ItemNetherWart.h2
-rw-r--r--src/Items/ItemPainting.h8
-rw-r--r--src/Items/ItemPotion.h199
-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/ItemSign.h2
-rw-r--r--src/Items/ItemString.h39
-rw-r--r--src/Items/ItemSugarcane.h2
-rw-r--r--src/Items/ItemThrowable.h15
29 files changed, 426 insertions, 138 deletions
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/ItemBow.h b/src/Items/ItemBow.h
index 821e2ab26..e7a77dcbc 100644
--- a/src/Items/ItemBow.h
+++ b/src/Items/ItemBow.h
@@ -46,20 +46,17 @@ 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)
@@ -72,9 +69,8 @@ public:
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..6d7926fa4 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;
}
@@ -138,7 +124,7 @@ public:
}
// 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 3b1ad1717..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:
@@ -201,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));
@@ -237,3 +246,7 @@ public:
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/ItemHandler.cpp b/src/Items/ItemHandler.cpp
index f639423ae..178bc2fca 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)
@@ -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:
@@ -356,7 +362,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;
@@ -452,14 +458,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);
}
@@ -468,33 +474,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;
}
@@ -535,7 +525,7 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
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
)
@@ -552,7 +542,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
);
@@ -578,7 +568,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 e13198cd7..c7362c5f4 100644
--- a/src/Items/ItemHandler.h
+++ b/src/Items/ItemHandler.h
@@ -28,7 +28,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);
@@ -60,7 +60,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,24 +82,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);
/** 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.
+ /** 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);
@@ -109,11 +112,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/ItemItemFrame.h b/src/Items/ItemItemFrame.h
index b258b4aea..87e20ecf0 100644
--- a/src/Items/ItemItemFrame.h
+++ b/src/Items/ItemItemFrame.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)
{
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 bc650cdbd..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
}
@@ -57,7 +57,7 @@ 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;
}
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/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 e4bb76ebe..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[] =
diff --git a/src/Items/ItemPotion.h b/src/Items/ItemPotion.h
new file mode 100644
index 000000000..f3afbf99b
--- /dev/null
+++ b/src/Items/ItemPotion.h
@@ -0,0 +1,199 @@
+
+#pragma once
+
+#include "../Entities/EntityEffect.h"
+#include "../Entities/SplashPotionEntity.h"
+
+class cItemPotionHandler:
+ public cItemHandler
+{
+ typedef cItemHandler super;
+
+public:
+
+ cItemPotionHandler():
+ super(E_ITEM_POTION)
+ {
+ }
+
+
+ /** Returns the potion particle type (used by the client for visuals), based on the potion's damage value */
+ static int GetPotionParticleType(short a_ItemDamage)
+ {
+ // Lowest six bits
+ return (a_ItemDamage & 0x3f);
+ }
+
+
+ /** Translates the potion's damage value into the entity effect that the potion gives */
+ static cEntityEffect::eType GetEntityEffectType(short a_ItemDamage)
+ {
+ // Lowest four bits
+ // Potion effect bits are different from entity effect values
+ // For reference: http://minecraft.gamepedia.com/Data_values#.22Potion_effect.22_bits
+ switch (a_ItemDamage & 0x0f)
+ {
+ case 0x01: return cEntityEffect::effRegeneration;
+ case 0x02: return cEntityEffect::effSpeed;
+ case 0x03: return cEntityEffect::effFireResistance;
+ case 0x04: return cEntityEffect::effPoison;
+ case 0x05: return cEntityEffect::effInstantHealth;
+ case 0x06: return cEntityEffect::effNightVision;
+ case 0x08: return cEntityEffect::effWeakness;
+ case 0x09: return cEntityEffect::effStrength;
+ case 0x0a: return cEntityEffect::effSlowness;
+ case 0x0c: return cEntityEffect::effInstantDamage;
+ case 0x0d: return cEntityEffect::effWaterBreathing;
+ case 0x0e: return cEntityEffect::effInvisibility;
+
+ // No effect potions
+ case 0x00:
+ case 0x07:
+ case 0x0b: // Will be potion of leaping in 1.8
+ case 0x0f:
+ {
+ break;
+ }
+ }
+ return cEntityEffect::effNoEffect;
+ }
+
+
+ /** Retrieves the intensity level from the potion's damage value.
+ Returns 0 for level I potions, 1 for level II potions. */
+ static short GetEntityEffectIntensity(short a_ItemDamage)
+ {
+ // Level II potion if the fifth lowest bit is set
+ return ((a_ItemDamage & 0x20) != 0) ? 1 : 0;
+ }
+
+
+ /** Returns the effect duration, in ticks, based on the potion's damage value */
+ static int GetEntityEffectDuration(short a_ItemDamage)
+ {
+ // Base duration in ticks
+ int base = 0;
+ double TierCoeff = 1, ExtCoeff = 1, SplashCoeff = 1;
+
+ switch (GetEntityEffectType(a_ItemDamage))
+ {
+ case cEntityEffect::effRegeneration:
+ case cEntityEffect::effPoison:
+ {
+ base = 900;
+ break;
+ }
+
+ case cEntityEffect::effSpeed:
+ case cEntityEffect::effFireResistance:
+ case cEntityEffect::effNightVision:
+ case cEntityEffect::effStrength:
+ case cEntityEffect::effWaterBreathing:
+ case cEntityEffect::effInvisibility:
+ {
+ base = 3600;
+ break;
+ }
+
+ case cEntityEffect::effWeakness:
+ case cEntityEffect::effSlowness:
+ {
+ base = 1800;
+ break;
+ }
+ }
+
+ // If potion is level II, half the duration. If not, stays the same
+ TierCoeff = (GetEntityEffectIntensity(a_ItemDamage) > 0) ? 0.5 : 1;
+
+ // If potion is extended, multiply duration by 8/3. If not, stays the same
+ // Extended potion if sixth lowest bit is set
+ ExtCoeff = (a_ItemDamage & 0x40) ? (8.0 / 3.0) : 1;
+
+ // If potion is splash potion, multiply duration by 3/4. If not, stays the same
+ SplashCoeff = IsPotionDrinkable(a_ItemDamage) ? 1 : 0.75;
+
+ // Ref.:
+ // http://minecraft.gamepedia.com/Data_values#.22Tier.22_bit
+ // http://minecraft.gamepedia.com/Data_values#.22Extended_duration.22_bit
+ // http://minecraft.gamepedia.com/Data_values#.22Splash_potion.22_bit
+
+ return (int)(base * TierCoeff * ExtCoeff * SplashCoeff);
+ }
+
+
+ /** Returns true if the potion with the given damage is drinkable */
+ static bool IsPotionDrinkable(short a_ItemDamage)
+ {
+ // Drinkable potion if 13th lowest bit is set
+ // Ref.: http://minecraft.gamepedia.com/Potions#Data_value_table
+ return ((a_ItemDamage & 0x2000) != 0);
+ }
+
+
+ // 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 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 (IsPotionDrinkable(PotionDamage))
+ {
+ return false;
+ }
+
+ Vector3d Pos = a_Player->GetThrowStartPos();
+ Vector3d Speed = a_Player->GetLookVector() * 7;
+
+ cSplashPotionEntity * Projectile = new cSplashPotionEntity(
+ a_Player, Pos.x, Pos.y, Pos.z, Speed,
+ GetEntityEffectType(PotionDamage), cEntityEffect(GetEntityEffectDuration(PotionDamage),
+ GetEntityEffectIntensity(PotionDamage)), GetPotionParticleType(PotionDamage)
+ );
+ if (Projectile == NULL)
+ {
+ return false;
+ }
+ if (!Projectile->Initialize(*a_World))
+ {
+ delete Projectile;
+ 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 (!IsDrinkable(a_Item->m_ItemDamage))
+ {
+ return false;
+ }
+
+ a_Player->AddEntityEffect(GetEntityEffectType(PotionDamage), GetEntityEffectDuration(PotionDamage), GetEntityEffectIntensity(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/ItemSign.h b/src/Items/ItemSign.h
index 60cf0f5f8..235a4fa93 100644
--- a/src/Items/ItemSign.h
+++ b/src/Items/ItemSign.h
@@ -27,7 +27,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/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/ItemThrowable.h b/src/Items/ItemThrowable.h
index 25935a1bc..c151c5d3a 100644
--- a/src/Items/ItemThrowable.h
+++ b/src/Items/ItemThrowable.h
@@ -33,16 +33,9 @@ public:
// Play sound
cFastRandom Random;
- a_World->BroadcastSoundEffect(
- "random.bow",
- (int)std::floor(a_Player->GetPosX() * 8.0),
- (int)std::floor((a_Player->GetPosY() - a_Player->GetHeight()) * 8.0),
- (int)std::floor(a_Player->GetPosZ() * 8.0),
- 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)
+ 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;
}
@@ -142,7 +135,7 @@ public:
return false;
}
- if (a_World->CreateProjectile(a_BlockX + 0.5, a_BlockY + 1, a_BlockZ + 0.5, m_ProjectileKind, a_Player, a_Player->GetEquippedItem()) < 0)
+ 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;
}