1
0

Merged branch "branches/hooks" into "trunk".

git-svn-id: http://mc-server.googlecode.com/svn/trunk@1139 0a769ca7-a7f5-676a-18bf-c427514a06d6
This commit is contained in:
madmaxoft@gmail.com 2013-01-12 04:46:01 +00:00
parent 71d71410fd
commit 43e6840719
113 changed files with 3762 additions and 5535 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
/* /*
** Lua binding: AllToLua ** Lua binding: AllToLua
** Generated automatically by tolua++-1.0.92 on 01/04/13 18:19:46. ** Generated automatically by tolua++-1.0.92 on 01/12/13 17:47:55.
*/ */
/* Exported function */ /* Exported function */

View File

@ -255,7 +255,7 @@ AString ItemTypeToString(short a_ItemType)
AString ItemToFullString(const cItem & a_Item) AString ItemToFullString(const cItem & a_Item)
{ {
AString res; AString res;
Printf(res, "%s:%d * %d", ItemToString(a_Item).c_str(), a_Item.m_ItemHealth, a_Item.m_ItemCount); Printf(res, "%s:%d * %d", ItemToString(a_Item).c_str(), a_Item.m_ItemDamage, a_Item.m_ItemCount);
return res; return res;
} }

View File

@ -161,6 +161,11 @@ enum ENUM_BLOCK_ID
E_BLOCK_POTATOES = 142, E_BLOCK_POTATOES = 142,
E_BLOCK_WOODEN_BUTTON = 143, E_BLOCK_WOODEN_BUTTON = 143,
E_BLOCK_HEAD = 144, E_BLOCK_HEAD = 144,
// Keep these two as the last values, without a number - they will get their correct number assigned automagically by C++
// IsValidBlock() depends on this
E_BLOCK_NUMBER_OF_TYPES, ///< Number of individual (different) blocktypes
E_BLOCK_MAX_TYPE_ID = E_BLOCK_NUMBER_OF_TYPES - 1 ///< Maximum BlockType number used
}; };
// tolua_end // tolua_end
@ -303,6 +308,8 @@ enum ENUM_ITEM_ID
E_ITEM_TRIPWIRE = 132, E_ITEM_TRIPWIRE = 132,
E_ITEM_EMERALD_BLOCK = 133, E_ITEM_EMERALD_BLOCK = 133,
E_ITEM_FIRST = 256, // First true item type
E_ITEM_IRON_SHOVEL = 256, E_ITEM_IRON_SHOVEL = 256,
E_ITEM_IRON_PICKAXE = 257, E_ITEM_IRON_PICKAXE = 257,
E_ITEM_IRON_AXE = 258, E_ITEM_IRON_AXE = 258,
@ -446,6 +453,12 @@ enum ENUM_ITEM_ID
E_ITEM_FIREWORK_STAR = 402, E_ITEM_FIREWORK_STAR = 402,
E_ITEM_ENCHANTED_BOOK = 403, E_ITEM_ENCHANTED_BOOK = 403,
// Keep these two as the last values of the consecutive list, without a number - they will get their correct number assigned automagically by C++
// IsValidItem() depends on this!
E_ITEM_NUMBER_OF_CONSECUTIVE_TYPES, ///< Number of individual (different) consecutive itemtypes
E_ITEM_MAX_CONSECUTIVE_TYPE_ID = E_ITEM_NUMBER_OF_CONSECUTIVE_TYPES - 1, ///< Maximum consecutive ItemType number used
E_ITEM_FIRST_DISC = 2256,
E_ITEM_13_DISC = 2256, E_ITEM_13_DISC = 2256,
E_ITEM_CAT_DISC = 2257, E_ITEM_CAT_DISC = 2257,
E_ITEM_BLOCKS_DISC = 2258, E_ITEM_BLOCKS_DISC = 2258,
@ -457,7 +470,12 @@ enum ENUM_ITEM_ID
E_ITEM_STRAD_DISC = 2264, E_ITEM_STRAD_DISC = 2264,
E_ITEM_WARD_DISC = 2265, E_ITEM_WARD_DISC = 2265,
E_ITEM_11_DISC = 2266, E_ITEM_11_DISC = 2266,
E_ITEM_WAIT_DISC = 2267 E_ITEM_WAIT_DISC = 2267,
// Keep these two as the last values of the disc list, without a number - they will get their correct number assigned automagically by C++
// IsValidItem() depends on this!
E_ITEM_LAST_DISC_PLUS_ONE, ///< Useless, really, but needs to be present for the following value
E_ITEM_LAST_DISC = E_ITEM_LAST_DISC_PLUS_ONE - 1 ///< Maximum disc itemtype number used
}; };

View File

@ -5,25 +5,18 @@
void cBlockBedHandler::PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) void cBlockBedHandler::OnPlacedByPlayer(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
)
{ {
if (a_Dir != 1) // Can only be placed on the floor if (a_BlockMeta < 8)
{ {
return; Vector3i Direction = MetaDataToDirection(a_BlockMeta);
a_World->SetBlock(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z, E_BLOCK_BED, a_BlockMeta | 0x8);
} }
NIBBLETYPE Meta = RotationToMetaData( a_Player->GetRotation() );
Vector3i Direction = MetaDataToDirection( Meta );
if (a_World->GetBlock(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z) != E_BLOCK_AIR)
{
return;
}
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_BED, Meta);
a_World->SetBlock(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z, E_BLOCK_BED, Meta | 0x8);
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
} }
@ -58,7 +51,7 @@ void cBlockBedHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY,
void cBlockBedHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockBedHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{ {
NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (Meta & 0x8) if (Meta & 0x8)
@ -74,7 +67,6 @@ void cBlockBedHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, i
{ {
a_World->BroadcastUseBed(*a_Player, a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z); a_World->BroadcastUseBed(*a_Player, a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z);
} }
} }
} }

View File

@ -20,9 +20,9 @@ public:
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override; virtual void OnPlacedByPlayer(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual bool IsUseable(void) override virtual bool IsUseable(void) override

View File

@ -19,12 +19,66 @@ public:
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
a_BlockType = m_BlockType;
// Is there a doublechest already next to this block?
if (!CanBeAt(a_World, a_BlockX, a_BlockY, a_BlockZ))
{
// Yup, cannot form a triple-chest, refuse:
return false;
}
// Check if this forms a doublechest, if so, need to adjust the meta:
cBlockArea Area;
if (!Area.Read(a_World, a_BlockX - 1, a_BlockX + 1, a_BlockY, a_BlockY, a_BlockZ - 1, a_BlockZ + 1))
{
return false;
}
float rot = a_Player->GetRotation();
if (
(Area.GetRelBlockType(0, 0, 1) == E_BLOCK_CHEST) ||
(Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
)
{
a_BlockMeta = ((rot >= -90) && (rot < 90)) ? 2 : 3;
return true;
}
if (
(Area.GetRelBlockType(0, 0, 1) == E_BLOCK_CHEST) ||
(Area.GetRelBlockType(2, 0, 1) == E_BLOCK_CHEST)
)
{
a_BlockMeta = (rot < 0) ? 4 : 5;
return true;
}
// Single chest, get meta from rotation only
a_BlockMeta = RotationToMetaData(rot);
return true;
}
virtual void OnPlacedByPlayer(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
) override
{ {
// Check if this forms a doublechest, if so, need to adjust the meta: // Check if this forms a doublechest, if so, need to adjust the meta:
cBlockArea Area; cBlockArea Area;
if (Area.Read(a_World, a_BlockX - 1, a_BlockX + 1, a_BlockY, a_BlockY, a_BlockZ - 1, a_BlockZ + 1)) if (!Area.Read(a_World, a_BlockX - 1, a_BlockX + 1, a_BlockY, a_BlockY, a_BlockZ - 1, a_BlockZ + 1))
{ {
return;
}
float rot = a_Player->GetRotation(); float rot = a_Player->GetRotation();
// Choose meta from player rotation, choose only between 2 or 3 // Choose meta from player rotation, choose only between 2 or 3
NIBBLETYPE NewMeta = ((rot >= -90) && (rot < 90)) ? 2 : 3; NIBBLETYPE NewMeta = ((rot >= -90) && (rot < 90)) ? 2 : 3;
@ -34,8 +88,6 @@ public:
) )
{ {
// Forming a double chest in the X direction // Forming a double chest in the X direction
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, NewMeta);
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
return; return;
} }
// Choose meta from player rotation, choose only between 4 or 5 // Choose meta from player rotation, choose only between 4 or 5
@ -46,14 +98,10 @@ public:
) )
{ {
// Forming a double chest in the Z direction // Forming a double chest in the Z direction
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, NewMeta);
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
return; return;
} }
}
// Single chest or unable to read neighbors (don't really care, then): // Single chest, no further processing needed
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, RotationToMetaData(a_Player->GetRotation()));
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
} }

View File

@ -14,16 +14,25 @@ class cBlockDispenserHandler :
public cBlockEntityHandler public cBlockEntityHandler
{ {
public: public:
cBlockDispenserHandler(BLOCKTYPE a_BlockType) cBlockDispenserHandler(BLOCKTYPE a_BlockType) :
: cBlockEntityHandler(a_BlockType) cBlockEntityHandler(a_BlockType)
{ {
} }
virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0)); a_BlockType = m_BlockType;
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir); a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0);
return true;
} }
} ; } ;

View File

@ -19,18 +19,9 @@ cBlockDoorHandler::cBlockDoorHandler(BLOCKTYPE a_BlockType)
void cBlockDoorHandler::OnPlaced(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir)
{
}
void cBlockDoorHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockDoorHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
char OldMeta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); NIBBLETYPE OldMeta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if (OldMeta & 8) if (OldMeta & 8)
{ {
@ -54,7 +45,7 @@ void cBlockDoorHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY
void cBlockDoorHandler::OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockDoorHandler::OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{ {
cDoors::ChangeDoor(a_World, a_BlockX, a_BlockY, a_BlockZ); cDoors::ChangeDoor(a_World, a_BlockX, a_BlockY, a_BlockZ);
} }
@ -63,23 +54,24 @@ void cBlockDoorHandler::OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX
void cBlockDoorHandler::PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) void cBlockDoorHandler::OnPlacedByPlayer(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
)
{ {
if (a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ) == E_BLOCK_AIR) NIBBLETYPE a_TopBlockMeta = 8;
{ if (
a_BlockMeta = cDoors::RotationToMetaData(a_Player->GetRotation()); (a_BlockMeta == 0) && (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1) == m_BlockType) ||
char a_TopBlockMeta = 8;
if( (a_BlockMeta == 0) && (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1) == m_BlockType) ||
(a_BlockMeta == 1) && (a_World->GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ) == m_BlockType) || (a_BlockMeta == 1) && (a_World->GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ) == m_BlockType) ||
(a_BlockMeta == 2) && (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1) == m_BlockType) || (a_BlockMeta == 2) && (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1) == m_BlockType) ||
(a_BlockMeta == 3) && (a_World->GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ) == m_BlockType)) (a_BlockMeta == 3) && (a_World->GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ) == m_BlockType)
)
{ {
a_TopBlockMeta = 9; a_TopBlockMeta = 9;
} }
a_World->SetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, m_BlockType, a_TopBlockMeta); a_World->SetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, m_BlockType, a_TopBlockMeta);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, a_BlockMeta);
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
}
} }

View File

@ -3,6 +3,8 @@
#include "BlockHandler.h" #include "BlockHandler.h"
#include "../World.h" #include "../World.h"
#include "../Doors.h"
#include "../Player.h"
@ -13,32 +15,89 @@ class cBlockDoorHandler :
{ {
public: public:
cBlockDoorHandler(BLOCKTYPE a_BlockType); cBlockDoorHandler(BLOCKTYPE a_BlockType);
virtual void OnPlaced(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir) override;
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual const char * GetStepSound(void) override; virtual const char * GetStepSound(void) override;
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
// If clicking a bottom face, place the door one block lower:
if (a_BlockFace == BLOCK_FACE_BOTTOM)
{
a_BlockY--;
}
if (
!CanReplaceBlock(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ)) ||
!CanReplaceBlock(a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))
)
{
return false;
}
a_BlockType = m_BlockType;
a_BlockMeta = cDoors::RotationToMetaData(a_Player->GetRotation());
return true;
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{ {
a_Pickups.push_back(cItem((m_BlockType == E_BLOCK_WOODEN_DOOR) ? E_ITEM_WOODEN_DOOR : E_ITEM_IRON_DOOR, 1, 0)); a_Pickups.push_back(cItem((m_BlockType == E_BLOCK_WOODEN_DOOR) ? E_ITEM_WOODEN_DOOR : E_ITEM_IRON_DOOR, 1, 0));
} }
virtual bool IsUseable() override
virtual void OnPlacedByPlayer(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
) override;
virtual bool IsUseable(void) override
{ {
return true; return true;
} }
virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override;
virtual bool CanBePlacedOnSide(void) override virtual bool CanBePlacedOnSide(void) override
{ {
return false; return false;
} }
virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
{ {
return (a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) != E_BLOCK_AIR); return (a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ) != E_BLOCK_AIR);
} }
bool CanReplaceBlock(BLOCKTYPE a_BlockType)
{
switch (a_BlockType)
{
case E_BLOCK_AIR:
case E_BLOCK_TALL_GRASS:
case E_BLOCK_WATER:
case E_BLOCK_STATIONARY_WATER:
case E_BLOCK_LAVA:
case E_BLOCK_STATIONARY_LAVA:
case E_BLOCK_SNOW:
case E_BLOCK_FIRE:
{
return true;
}
}
return false;
}
} ; } ;

View File

@ -15,7 +15,7 @@ public:
{ {
} }
virtual void OnUse(cWorld * a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override virtual void OnUse(cWorld * a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{ {
a_World->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ); a_World->UseBlockEntity(a_Player, a_BlockX, a_BlockY, a_BlockZ);
} }

View File

@ -12,27 +12,29 @@ class cBlockFenceGateHandler :
public cBlockHandler public cBlockHandler
{ {
public: public:
cBlockFenceGateHandler(BLOCKTYPE a_BlockType) cBlockFenceGateHandler(BLOCKTYPE a_BlockType) :
: cBlockHandler(a_BlockType) cBlockHandler(a_BlockType)
{ {
} }
void OnPlaced(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir)
{
} virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
a_BlockType = m_BlockType;
a_BlockMeta = cDoors::RotationToMetaData(a_Player->GetRotation() + 270); a_BlockMeta = cDoors::RotationToMetaData(a_Player->GetRotation() + 270);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, a_BlockMeta); return true;
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
} }
void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{ {
char OldMetaData = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); NIBBLETYPE OldMetaData = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
char NewMetaData = cDoors::RotationToMetaData(a_Player->GetRotation() + 270); NIBBLETYPE NewMetaData = cDoors::RotationToMetaData(a_Player->GetRotation() + 270);
OldMetaData ^= 4; //Toggle the gate OldMetaData ^= 4; //Toggle the gate
if ((OldMetaData & 1) == (NewMetaData & 1)) if ((OldMetaData & 1) == (NewMetaData & 1))
{ {
@ -46,7 +48,8 @@ public:
} }
} }
virtual bool IsUseable() override
virtual bool IsUseable(void) override
{ {
return true; return true;
} }

View File

@ -11,15 +11,19 @@ class cBlockFlowerPotHandler :
public cBlockHandler public cBlockHandler
{ {
public: public:
cBlockFlowerPotHandler(BLOCKTYPE a_BlockType) cBlockFlowerPotHandler(BLOCKTYPE a_BlockType) :
: cBlockHandler(a_BlockType) cBlockHandler(a_BlockType)
{ {
} }
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{ {
a_Pickups.push_back(cItem(E_ITEM_FLOWER_POT, 1, 0)); a_Pickups.push_back(cItem(E_ITEM_FLOWER_POT, 1, 0));
if( a_BlockMeta == 0 ) return; if (a_BlockMeta == 0)
{
return;
}
cItem Plant; cItem Plant;
switch (a_BlockMeta) switch (a_BlockMeta)
{ {
@ -34,14 +38,21 @@ public:
case 9: Plant = cItem(E_ITEM_CACTUS, 1, 0); break; case 9: Plant = cItem(E_ITEM_CACTUS, 1, 0); break;
case 10: Plant = cItem(E_BLOCK_DEAD_BUSH, 1, 0); break; case 10: Plant = cItem(E_BLOCK_DEAD_BUSH, 1, 0); break;
case 11: Plant = cItem(E_BLOCK_TALL_GRASS, 1, E_META_TALL_GRASS_FERN); break; case 11: Plant = cItem(E_BLOCK_TALL_GRASS, 1, E_META_TALL_GRASS_FERN); break;
default: return;
} }
a_Pickups.push_back(Plant); a_Pickups.push_back(Plant);
} }
void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
char Meta = a_World->GetBlockMeta( a_BlockX, a_BlockY, a_BlockZ ); NIBBLETYPE Meta = a_World->GetBlockMeta( a_BlockX, a_BlockY, a_BlockZ );
if( Meta ) return; if (Meta != 0)
{
// Already filled
return;
}
switch (a_Player->GetEquippedItem().m_ItemType) switch (a_Player->GetEquippedItem().m_ItemType)
{ {
case E_ITEM_RED_ROSE: Meta = 1; break; case E_ITEM_RED_ROSE: Meta = 1; break;
@ -62,8 +73,19 @@ public:
case E_ITEM_CACTUS: Meta = 9; break; case E_ITEM_CACTUS: Meta = 9; break;
case E_BLOCK_DEAD_BUSH: Meta = 10; break; case E_BLOCK_DEAD_BUSH: Meta = 10; break;
case E_BLOCK_TALL_GRASS: case E_BLOCK_TALL_GRASS:
if( a_Player->GetEquippedItem().m_ItemDamage == E_META_TALL_GRASS_FERN ) Meta = 11; break; {
if (a_Player->GetEquippedItem().m_ItemDamage == E_META_TALL_GRASS_FERN)
{
Meta = 11;
} }
else
{
return;
}
break;
}
}
if (a_Player->GetGameMode() != eGameMode_Creative) if (a_Player->GetGameMode() != eGameMode_Creative)
{ {
cItem Item(a_Player->GetEquippedItem().m_ItemType, 1); cItem Item(a_Player->GetEquippedItem().m_ItemType, 1);
@ -72,7 +94,8 @@ public:
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta); a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
} }
virtual bool IsUseable() override
virtual bool IsUseable(void) override
{ {
return true; return true;
} }

View File

@ -14,8 +14,8 @@ class cBlockFurnaceHandler :
public cBlockEntityHandler public cBlockEntityHandler
{ {
public: public:
cBlockFurnaceHandler(BLOCKTYPE a_BlockType) cBlockFurnaceHandler(BLOCKTYPE a_BlockType) :
: cBlockEntityHandler(a_BlockType) cBlockEntityHandler(a_BlockType)
{ {
} }
@ -26,10 +26,16 @@ public:
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0)); a_BlockType = m_BlockType;
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir); a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetRotation(), 0);
return true;
} }
} ; } ;

View File

@ -207,6 +207,23 @@ cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
bool cBlockHandler::GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
)
{
// By default, all blocks can be placed and the meta is copied over from the item's damage value:
a_BlockType = m_BlockType;
a_BlockMeta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage & 0x0f);
return true;
}
void cBlockHandler::OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockHandler::OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
} }
@ -215,7 +232,7 @@ void cBlockHandler::OnUpdate(cWorld * a_World, int a_BlockX, int a_BlockY, int a
void cBlockHandler::OnPlacedByPlayer(cWorld *a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir) void cBlockHandler::OnPlacedByPlayer(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{ {
} }
@ -231,7 +248,7 @@ void cBlockHandler::OnDestroyedByPlayer(cWorld *a_World, cPlayer * a_Player, int
void cBlockHandler::OnPlaced(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir) void cBlockHandler::OnPlaced(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{ {
// Notify the neighbors // Notify the neighbors
NeighborChanged(a_World, a_BlockX - 1, a_BlockY, a_BlockZ); NeighborChanged(a_World, a_BlockX - 1, a_BlockY, a_BlockZ);
@ -286,7 +303,7 @@ void cBlockHandler::OnDigging(cWorld *a_World, cPlayer *a_Player, int a_BlockX,
void cBlockHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{ {
} }
@ -294,16 +311,6 @@ void cBlockHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int
void cBlockHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir)
{
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, a_BlockMeta);
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
}
void cBlockHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) void cBlockHandler::ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta)
{ {
// Setting the meta to a_BlockMeta keeps most textures. The few other blocks have to override this. // Setting the meta to a_BlockMeta keeps most textures. The few other blocks have to override this.

View File

@ -21,18 +21,35 @@ class cBlockHandler
public: public:
cBlockHandler(BLOCKTYPE a_BlockType); cBlockHandler(BLOCKTYPE a_BlockType);
// Called when the block gets ticked either by a random tick or by a queued tick /// Called when the block gets ticked either by a random tick or by a queued tick
virtual void OnUpdate(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ); virtual void OnUpdate(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ);
/// Called by cBlockHandler::PlaceBlock after the player has placed a new block /** Called before a block is placed into a world.
virtual void OnPlacedByPlayer(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir); 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.
Called by cItemHandler::GetPlacementBlockTypeMeta() if the item is a block
*/
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
);
/// Called by cWorld::SetBlock() after the block has been set
virtual void OnPlaced(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
/// Called by cClientHandle::HandlePlaceBlock() after the player has placed a new block. Called after OnPlaced().
virtual void OnPlacedByPlayer(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta
);
/// Called before the player has destroyed a block /// Called before the player has destroyed a block
virtual void OnDestroyedByPlayer(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ); virtual void OnDestroyedByPlayer(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ);
/// Called when a new block was placed. Called before OnPlacedByPlayer
virtual void OnPlaced(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir);
/// Called before a block gets destroyed / replaced with air /// Called before a block gets destroyed / replaced with air
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ); virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ);
@ -46,10 +63,7 @@ public:
virtual void OnDigging(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ); virtual void OnDigging(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ);
/// Called if the user right clicks the block and the block is useable /// Called if the user right clicks the block and the block is useable
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ); virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
/// This function handles the real block placement for the give block by a player and also calls OnPlacedByPlayer()
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
/// Called when the item is mined to convert it into pickups. Pickups may specify multiple items. /// Called when the item is mined to convert it into pickups. Pickups may specify multiple items.
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta); virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta);

View File

@ -19,61 +19,70 @@ public:
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
if (!LadderCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_Dir)) if (!LadderCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
{ {
a_Dir = FindSuitableDirection(a_World, a_BlockX, a_BlockY, a_BlockZ); a_BlockFace = FindSuitableBlockFace(a_World, a_BlockX, a_BlockY, a_BlockZ);
if (a_Dir == BLOCK_FACE_BOTTOM) if (a_BlockFace == BLOCK_FACE_BOTTOM)
{ {
return; return false;
} }
} }
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, cLadder::DirectionToMetaData(a_Dir)); a_BlockType = m_BlockType;
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir); a_BlockMeta = cLadder::DirectionToMetaData(a_BlockFace);
return true;
} }
/// Finds a suitable Direction for the Ladder. Returns BLOCK_FACE_BOTTOM on failure /// Finds a suitable Direction for the Ladder. Returns BLOCK_FACE_BOTTOM on failure
static char FindSuitableDirection(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) static char FindSuitableBlockFace(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
for (int i = 2; i <= 5; i++) for (int Face = 2; Face <= 5; Face++)
{ {
if (LadderCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, i)) if (LadderCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, Face))
{ {
return i; return Face;
} }
} }
return BLOCK_FACE_BOTTOM; return BLOCK_FACE_BOTTOM;
} }
static bool LadderCanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) static bool LadderCanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{ {
if (a_Dir == BLOCK_FACE_BOTTOM || a_Dir == BLOCK_FACE_TOP ) if ((a_BlockFace == BLOCK_FACE_BOTTOM) || (a_BlockFace == BLOCK_FACE_TOP))
{ {
return false; return false;
} }
AddDirection( a_BlockX, a_BlockY, a_BlockZ, a_Dir, true ); AddFaceDirection( a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true);
return g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ)]; return g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ)];
} }
virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
{
if (LadderCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
{ {
if (LadderCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_Dir))
return true; return true;
return FindSuitableDirection(a_World, a_BlockX, a_BlockY, a_BlockZ) != BLOCK_FACE_BOTTOM; }
return (FindSuitableBlockFace(a_World, a_BlockX, a_BlockY, a_BlockZ) != BLOCK_FACE_BOTTOM);
} }
virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
{ {
char Dir = cLadder::MetaDataToDirection(a_World->GetBlockMeta( a_BlockX, a_BlockY, a_BlockZ)); char BlockFace = cLadder::MetaDataToDirection(a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
return CanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, Dir); return CanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, BlockFace);
} }

View File

@ -19,25 +19,7 @@ cBlockLeverHandler::cBlockLeverHandler(BLOCKTYPE a_BlockType)
void cBlockLeverHandler::OnPlaced(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir) void cBlockLeverHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
// Noting needed yet
}
void cBlockLeverHandler::OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{
// Nothing needed yet
}
void cBlockLeverHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
// Flip the ON bit on/off. Using XOR bitwise operation to turn it on/off. // Flip the ON bit on/off. Using XOR bitwise operation to turn it on/off.
NIBBLETYPE Meta = ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f); NIBBLETYPE Meta = ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f);
@ -58,17 +40,7 @@ void cBlockLeverHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX,
void cBlockLeverHandler::OnDigging(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockLeverHandler::OnDigging(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
OnUse(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ); OnUse(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NONE, 8, 8, 8);
}
void cBlockLeverHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir)
{
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, cRedstoneSimulator::LeverDirectionToMetaData(a_Dir));
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
} }

View File

@ -2,6 +2,9 @@
#include "BlockHandler.h" #include "BlockHandler.h"
#include "../World.h" #include "../World.h"
#include "../Simulator/RedstoneSimulator.h"
@ -10,11 +13,9 @@ class cBlockLeverHandler :
{ {
public: public:
cBlockLeverHandler(BLOCKTYPE a_BlockType); cBlockLeverHandler(BLOCKTYPE a_BlockType);
virtual void OnPlaced(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir) override;
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnDigging(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnDigging(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
@ -30,7 +31,17 @@ public:
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override; virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
a_BlockType = m_BlockType;
a_BlockMeta = cRedstoneSimulator::LeverDirectionToMetaData(a_BlockFace);
return true;
}
virtual bool DoesAllowBlockOnTop(void) override virtual bool DoesAllowBlockOnTop(void) override
@ -38,8 +49,13 @@ public:
return false; return false;
} }
virtual const char * GetStepSound(void) override virtual const char * GetStepSound(void) override
{ {
return "step.wood"; return "step.wood";
} }
} ; } ;

View File

@ -33,14 +33,6 @@ cBlockPistonHandler::cBlockPistonHandler(BLOCKTYPE a_BlockType)
void cBlockPistonHandler::OnPlaced(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir)
{
}
void cBlockPistonHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockPistonHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
char OldMeta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); char OldMeta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
@ -60,11 +52,16 @@ void cBlockPistonHandler::OnDestroyed(cWorld * a_World, int a_BlockX, int a_Bloc
void cBlockPistonHandler::PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) bool cBlockPistonHandler::GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
)
{ {
a_BlockType = E_BLOCK_REDSTONE_REPEATER_OFF;
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, cPiston::RotationPitchToMetaData(a_Player->GetRotation(), a_Player->GetPitch())); a_BlockMeta = cPiston::RotationPitchToMetaData(a_Player->GetRotation(), a_Player->GetPitch());
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir); return true;
} }

View File

@ -1,15 +1,28 @@
#pragma once #pragma once
#include "BlockHandler.h" #include "BlockHandler.h"
class cBlockPistonHandler : public cBlockHandler
class cBlockPistonHandler :
public cBlockHandler
{ {
public: public:
cBlockPistonHandler(BLOCKTYPE a_BlockType); cBlockPistonHandler(BLOCKTYPE a_BlockType);
virtual void OnPlaced(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir) override;
virtual void OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual bool GetPlacementBlockTypeMeta(
virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override; cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override;
} ; } ;

View File

@ -42,84 +42,88 @@ public:
{ {
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, FindMeta(a_World, a_BlockX, a_BlockY, a_BlockZ)); a_BlockType = m_BlockType;
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir); a_BlockMeta = FindMeta(a_World, a_BlockX, a_BlockY, a_BlockZ);
NeighborChanged(a_World, a_BlockX - 1, a_BlockY + 1, a_BlockZ); return true;
NeighborChanged(a_World, a_BlockX + 1, a_BlockY + 1, a_BlockZ);
NeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ - 1);
NeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ + 1);
NeighborChanged(a_World, a_BlockX - 1, a_BlockY - 1, a_BlockZ);
NeighborChanged(a_World, a_BlockX + 1, a_BlockY - 1, a_BlockZ);
NeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ - 1);
NeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ + 1);
} }
virtual void OnNeighborChanged(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override virtual void OnNeighborChanged(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
{ {
char Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
if(IsUnstable(a_World, a_BlockX, a_BlockY, a_BlockZ) && Meta != FindMeta(a_World, a_BlockX, a_BlockY, a_BlockZ)) if (IsUnstable(a_World, a_BlockX, a_BlockY, a_BlockZ) && (Meta != FindMeta(a_World, a_BlockX, a_BlockY, a_BlockZ)))
{
a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, FindMeta(a_World, a_BlockX, a_BlockY, a_BlockZ)); a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, FindMeta(a_World, a_BlockX, a_BlockY, a_BlockZ));
} }
}
virtual bool CanBeAt(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override virtual bool CanBeAt(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
{ {
if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)]) if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ)])
{
return false; return false;
char Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); }
NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
switch (Meta) switch (Meta)
{ {
case E_RAIL_ASCEND_EAST: case E_RAIL_ASCEND_EAST:
{ {
if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ)]) if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX + 1, a_BlockY, a_BlockZ)])
{
return false; return false;
}
break; break;
} }
case E_RAIL_ASCEND_WEST: case E_RAIL_ASCEND_WEST:
{ {
if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ)]) if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX - 1, a_BlockY, a_BlockZ)])
{
return false; return false;
}
break; break;
} }
case E_RAIL_ASCEND_NORTH: case E_RAIL_ASCEND_NORTH:
{ {
if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1)]) if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ - 1)])
{
return false; return false;
}
break; break;
} }
case E_RAIL_ASCEND_SOUTH: case E_RAIL_ASCEND_SOUTH:
{ {
if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1)]) if (!g_BlockIsSolid[a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ + 1)])
{
return false; return false;
}
break; break;
} }
} }
return true; return true;
} }
char FindMeta(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) NIBBLETYPE FindMeta(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
char Meta = 0; NIBBLETYPE Meta = 0;
char RailsCnt = 0; char RailsCnt = 0;
bool Neighbors[8]; // 0 - EAST, 1 - WEST, 2 - NORTH, 3 - SOUTH, 4 - EAST UP, 5 - WEST UP, 6 - NORTH UP, 7 - SOUTH UP bool Neighbors[8]; // 0 - EAST, 1 - WEST, 2 - NORTH, 3 - SOUTH, 4 - EAST UP, 5 - WEST UP, 6 - NORTH UP, 7 - SOUTH UP
memset(Neighbors, false, sizeof(Neighbors)); memset(Neighbors, false, sizeof(Neighbors));
if(IsUnstable(a_World, a_BlockX + 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST, E_PURE_DOWN)) Neighbors[0] = (IsUnstable(a_World, a_BlockX + 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_EAST, E_PURE_DOWN));
Neighbors[0] = true; Neighbors[1] = (IsUnstable(a_World, a_BlockX - 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST, E_PURE_DOWN));
if(IsUnstable(a_World, a_BlockX - 1, a_BlockY, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_WEST, E_PURE_DOWN)) Neighbors[2] = (IsUnstable(a_World, a_BlockX, a_BlockY, a_BlockZ - 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_DOWN));
Neighbors[1] = true; Neighbors[3] = (IsUnstable(a_World, a_BlockX, a_BlockY, a_BlockZ + 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH, E_PURE_DOWN));
if(IsUnstable(a_World, a_BlockX, a_BlockY, a_BlockZ - 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_DOWN)) Neighbors[4] = (IsUnstable(a_World, a_BlockX + 1, a_BlockY + 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_EAST, E_PURE_NONE));
Neighbors[2] = true; Neighbors[5] = (IsUnstable(a_World, a_BlockX - 1, a_BlockY + 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_WEST, E_PURE_NONE));
if(IsUnstable(a_World, a_BlockX, a_BlockY, a_BlockZ + 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_SOUTH, E_PURE_DOWN)) Neighbors[6] = (IsUnstable(a_World, a_BlockX, a_BlockY + 1, a_BlockZ - 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_NONE));
Neighbors[3] = true; Neighbors[7] = (IsUnstable(a_World, a_BlockX, a_BlockY + 1, a_BlockZ + 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_SOUTH, E_PURE_NONE));
if(IsUnstable(a_World, a_BlockX + 1, a_BlockY + 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_EAST, E_PURE_NONE))
Neighbors[4] = true;
if(IsUnstable(a_World, a_BlockX - 1, a_BlockY + 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_WEST, E_PURE_NONE))
Neighbors[5] = true;
if(IsUnstable(a_World, a_BlockX, a_BlockY + 1, a_BlockZ - 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_NORTH, E_PURE_NONE))
Neighbors[6] = true;
if(IsUnstable(a_World, a_BlockX, a_BlockY + 1, a_BlockZ + 1) || !IsNotConnected(a_World, a_BlockX, a_BlockY + 1, a_BlockZ, BLOCK_FACE_SOUTH, E_PURE_NONE))
Neighbors[7] = true;
if (IsUnstable(a_World, a_BlockX + 1, a_BlockY - 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_EAST)) if (IsUnstable(a_World, a_BlockX + 1, a_BlockY - 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_EAST))
Neighbors[0] = true; Neighbors[0] = true;
if (IsUnstable(a_World, a_BlockX - 1, a_BlockY - 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_WEST)) if (IsUnstable(a_World, a_BlockX - 1, a_BlockY - 1, a_BlockZ) || !IsNotConnected(a_World, a_BlockX, a_BlockY - 1, a_BlockZ, BLOCK_FACE_WEST))
@ -137,12 +141,13 @@ public:
} }
if (RailsCnt == 1) if (RailsCnt == 1)
{ {
if(Neighbors[7]) Meta = E_RAIL_ASCEND_SOUTH; if (Neighbors[7]) return E_RAIL_ASCEND_SOUTH;
else if(Neighbors[6]) Meta = E_RAIL_ASCEND_NORTH; else if (Neighbors[6]) return E_RAIL_ASCEND_NORTH;
else if(Neighbors[5]) Meta = E_RAIL_ASCEND_WEST; else if (Neighbors[5]) return E_RAIL_ASCEND_WEST;
else if(Neighbors[4]) Meta = E_RAIL_ASCEND_EAST; else if (Neighbors[4]) return E_RAIL_ASCEND_EAST;
else if(Neighbors[0] || Neighbors[1]) Meta = E_RAIL_EAST_WEST; else if (Neighbors[0] || Neighbors[1]) return E_RAIL_EAST_WEST;
else if(Neighbors[2] || Neighbors[3]) Meta = E_RAIL_NORTH_SOUTH; else if (Neighbors[2] || Neighbors[3]) return E_RAIL_NORTH_SOUTH;
ASSERT(!"Weird neighbor count");
return Meta; return Meta;
} }
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
@ -154,24 +159,26 @@ public:
} }
if (RailsCnt > 1) if (RailsCnt > 1)
{ {
if(Neighbors[3] && Neighbors[0]) Meta = E_RAIL_CURVED_SOUTH_EAST; if (Neighbors[3] && Neighbors[0]) return E_RAIL_CURVED_SOUTH_EAST;
else if(Neighbors[3] && Neighbors[1]) Meta = E_RAIL_CURVED_SOUTH_WEST; else if(Neighbors[3] && Neighbors[1]) return E_RAIL_CURVED_SOUTH_WEST;
else if(Neighbors[2] && Neighbors[0]) Meta = E_RAIL_CURVED_NORTH_EAST; else if(Neighbors[2] && Neighbors[0]) return E_RAIL_CURVED_NORTH_EAST;
else if(Neighbors[2] && Neighbors[1]) Meta = E_RAIL_CURVED_NORTH_WEST; else if(Neighbors[2] && Neighbors[1]) return E_RAIL_CURVED_NORTH_WEST;
else if(Neighbors[7] && Neighbors[2]) Meta = E_RAIL_ASCEND_SOUTH; else if(Neighbors[7] && Neighbors[2]) return E_RAIL_ASCEND_SOUTH;
else if(Neighbors[3] && Neighbors[6]) Meta = E_RAIL_ASCEND_NORTH; else if(Neighbors[3] && Neighbors[6]) return E_RAIL_ASCEND_NORTH;
else if(Neighbors[5] && Neighbors[0]) Meta = E_RAIL_ASCEND_WEST; else if(Neighbors[5] && Neighbors[0]) return E_RAIL_ASCEND_WEST;
else if(Neighbors[4] && Neighbors[1]) Meta = E_RAIL_ASCEND_EAST; else if(Neighbors[4] && Neighbors[1]) return E_RAIL_ASCEND_EAST;
else if(Neighbors[0] && Neighbors[1]) Meta = E_RAIL_EAST_WEST; else if(Neighbors[0] && Neighbors[1]) return E_RAIL_EAST_WEST;
else if(Neighbors[2] && Neighbors[3]) Meta = E_RAIL_NORTH_SOUTH; else if(Neighbors[2] && Neighbors[3]) return E_RAIL_NORTH_SOUTH;
ASSERT(!"Weird neighbor count");
} }
return Meta; return Meta;
} }
bool IsUnstable(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) bool IsUnstable(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_RAIL) return false; if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_RAIL) return false;
char Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
switch (Meta) switch (Meta)
{ {
case E_RAIL_NORTH_SOUTH: case E_RAIL_NORTH_SOUTH:
@ -238,10 +245,11 @@ public:
return false; return false;
} }
bool IsNotConnected(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, char a_Pure = 0)
bool IsNotConnected(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Pure = 0)
{ {
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Direction, false); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false);
char Meta; NIBBLETYPE Meta;
if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_RAIL) if (a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_RAIL)
{ {
if ((a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ) != E_BLOCK_RAIL) || (a_Pure != E_PURE_UPDOWN)) if ((a_World->GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ) != E_BLOCK_RAIL) || (a_Pure != E_PURE_UPDOWN))
@ -264,46 +272,65 @@ public:
{ {
Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
} }
switch(a_Direction)
switch (a_BlockFace)
{ {
case BLOCK_FACE_NORTH: case BLOCK_FACE_NORTH:
{ {
if(Meta == E_RAIL_NORTH_SOUTH || if (
Meta == E_RAIL_ASCEND_NORTH || (Meta == E_RAIL_NORTH_SOUTH) ||
Meta == E_RAIL_ASCEND_SOUTH || (Meta == E_RAIL_ASCEND_NORTH) ||
Meta == E_RAIL_CURVED_SOUTH_EAST || (Meta == E_RAIL_ASCEND_SOUTH) ||
Meta == E_RAIL_CURVED_SOUTH_WEST) (Meta == E_RAIL_CURVED_SOUTH_EAST) ||
(Meta == E_RAIL_CURVED_SOUTH_WEST)
)
{
return false; return false;
}
break; break;
} }
case BLOCK_FACE_SOUTH: case BLOCK_FACE_SOUTH:
{ {
if(Meta == E_RAIL_NORTH_SOUTH || if (
Meta == E_RAIL_ASCEND_NORTH || (Meta == E_RAIL_NORTH_SOUTH) ||
Meta == E_RAIL_ASCEND_SOUTH || (Meta == E_RAIL_ASCEND_NORTH) ||
Meta == E_RAIL_CURVED_NORTH_EAST || (Meta == E_RAIL_ASCEND_SOUTH) ||
Meta == E_RAIL_CURVED_NORTH_WEST) (Meta == E_RAIL_CURVED_NORTH_EAST) ||
(Meta == E_RAIL_CURVED_NORTH_WEST)
)
{
return false; return false;
}
break; break;
} }
case BLOCK_FACE_EAST: case BLOCK_FACE_EAST:
{ {
if(Meta == E_RAIL_EAST_WEST || if (
Meta == E_RAIL_ASCEND_EAST || (Meta == E_RAIL_EAST_WEST) ||
Meta == E_RAIL_ASCEND_WEST || (Meta == E_RAIL_ASCEND_EAST) ||
Meta == E_RAIL_CURVED_SOUTH_WEST || (Meta == E_RAIL_ASCEND_WEST) ||
Meta == E_RAIL_CURVED_NORTH_WEST) (Meta == E_RAIL_CURVED_SOUTH_WEST) ||
(Meta == E_RAIL_CURVED_NORTH_WEST)
)
{
return false; return false;
}
break; break;
} }
case BLOCK_FACE_WEST: case BLOCK_FACE_WEST:
{ {
if(Meta == E_RAIL_EAST_WEST || if (
Meta == E_RAIL_ASCEND_EAST || (Meta == E_RAIL_EAST_WEST) ||
Meta == E_RAIL_ASCEND_WEST || (Meta == E_RAIL_ASCEND_EAST) ||
Meta == E_RAIL_CURVED_SOUTH_EAST || (Meta == E_RAIL_ASCEND_WEST) ||
Meta == E_RAIL_CURVED_NORTH_EAST) (Meta == E_RAIL_CURVED_SOUTH_EAST) ||
(Meta == E_RAIL_CURVED_NORTH_EAST)
)
{
return false; return false;
}
break; break;
} }
} }

View File

@ -18,15 +18,6 @@ cBlockRedstoneHandler::cBlockRedstoneHandler(BLOCKTYPE a_BlockType)
void cBlockRedstoneHandler::OnPlaced(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir)
{
// Nothing needed yet
}
void cBlockRedstoneHandler::OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockRedstoneHandler::OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
// Nothing needed yet // Nothing needed yet
@ -35,22 +26,3 @@ void cBlockRedstoneHandler::OnDestroyed(cWorld *a_World, int a_BlockX, int a_Blo
void cBlockRedstoneHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir)
{
switch(m_BlockType)
{
case E_BLOCK_REDSTONE_TORCH_ON:
case E_BLOCK_REDSTONE_TORCH_OFF:
{
a_BlockMeta = cTorch::DirectionToMetaData(a_Dir);
break;
}
}
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, a_BlockMeta);
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
}

View File

@ -13,12 +13,9 @@ class cBlockRedstoneHandler :
{ {
public: public:
cBlockRedstoneHandler(BLOCKTYPE a_BlockType); cBlockRedstoneHandler(BLOCKTYPE a_BlockType);
virtual void OnPlaced(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir) override;
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override;
virtual bool DoesAllowBlockOnTop(void) override virtual bool DoesAllowBlockOnTop(void) override
{ {
return false; return false;

View File

@ -19,15 +19,6 @@ cBlockRedstoneRepeaterHandler::cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockTy
void cBlockRedstoneRepeaterHandler::OnPlaced(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir)
{
// Noting needed yet
}
void cBlockRedstoneRepeaterHandler::OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockRedstoneRepeaterHandler::OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
// Nothing needed yet // Nothing needed yet
@ -37,7 +28,7 @@ void cBlockRedstoneRepeaterHandler::OnDestroyed(cWorld *a_World, int a_BlockX, i
void cBlockRedstoneRepeaterHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockRedstoneRepeaterHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{ {
a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) + 0x04) & 0x0f)); a_World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) + 0x04) & 0x0f));
} }
@ -48,17 +39,7 @@ void cBlockRedstoneRepeaterHandler::OnUse(cWorld *a_World, cPlayer *a_Player, in
void cBlockRedstoneRepeaterHandler::OnDigging(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) void cBlockRedstoneRepeaterHandler::OnDigging(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
OnUse(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ); OnUse(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, BLOCK_FACE_NONE, 8, 8, 8);
}
void cBlockRedstoneRepeaterHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir)
{
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, cRedstoneSimulator::RepeaterRotationToMetaData(a_Player->GetRotation()));
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
} }

View File

@ -13,11 +13,10 @@ class cBlockRedstoneRepeaterHandler :
{ {
public: public:
cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockType); cBlockRedstoneRepeaterHandler(BLOCKTYPE a_BlockType);
virtual void OnPlaced(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, int a_Dir) override;
virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnDestroyed(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnDigging(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnDigging(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
@ -33,9 +32,6 @@ public:
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override;
virtual bool DoesAllowBlockOnTop(void) override virtual bool DoesAllowBlockOnTop(void) override
{ {
return false; return false;

View File

@ -20,26 +20,6 @@ public:
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
BLOCKTYPE Block;
NIBBLETYPE Meta;
if (a_Dir == BLOCK_FACE_TOP)
{
Meta = cSign::RotationToMetaData(a_Player->GetRotation());
Block = E_BLOCK_SIGN_POST;
}
else
{
Meta = cSign::DirectionToMetaData(a_Dir);
Block = E_BLOCK_WALLSIGN;
}
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, Block, Meta);
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir);
}
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{ {
a_Pickups.push_back(cItem(E_ITEM_SIGN, 1, 0)); a_Pickups.push_back(cItem(E_ITEM_SIGN, 1, 0));

View File

@ -24,21 +24,38 @@ public:
} }
virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, DirectionToMetaData( a_Dir, a_BlockMeta )); a_BlockType = m_BlockType;
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir); NIBBLETYPE Meta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage & 0x07);
switch (a_BlockFace)
{
case BLOCK_FACE_TOP: a_BlockMeta = Meta & 0x7; break; // Always bottom half of the slab when placing on top of something
case BLOCK_FACE_BOTTOM: a_BlockMeta = Meta | 0x8; break; // Always top half of the slab when placing on bottom of something
case BLOCK_FACE_EAST:
case BLOCK_FACE_NORTH:
case BLOCK_FACE_SOUTH:
case BLOCK_FACE_WEST:
{
if (a_CursorY > 7)
{
// Cursor at the top half of the face, place a top half of slab
a_BlockMeta = Meta | 0x8;
} }
else
static char DirectionToMetaData( char a_Direction, NIBBLETYPE Meta )
{ {
char result = Meta; // Cursor at the bottom half of the face, place a bottom half of slab:
if( a_Direction == 0) a_BlockMeta = Meta & 0x7;
{
result |= 0x8;
} }
return result; break;
}
} // switch (a_BlockFace)
return true;
} }

View File

@ -1,22 +1,56 @@
#pragma once #pragma once
#include "BlockHandler.h" #include "BlockHandler.h"
#include "../Stairs.h" #include "../Stairs.h"
class cBlockStairsHandler : public cBlockHandler
class cBlockStairsHandler :
public cBlockHandler
{ {
public: public:
cBlockStairsHandler(BLOCKTYPE a_BlockType) cBlockStairsHandler(BLOCKTYPE a_BlockType) :
: cBlockHandler(a_BlockType) cBlockHandler(a_BlockType)
{ {
} }
virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, cStairs::RotationToMetaData(a_Player->GetRotation(), a_Dir)); a_BlockType = m_BlockType;
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir); a_BlockMeta = cStairs::RotationToMetaData(a_Player->GetRotation());
switch (a_BlockFace)
{
case BLOCK_FACE_TOP: break;
case BLOCK_FACE_BOTTOM: a_BlockMeta = a_BlockMeta | 0x4; break; // When placing onto a bottom face, always place an upside-down stairs block
case BLOCK_FACE_EAST:
case BLOCK_FACE_NORTH:
case BLOCK_FACE_SOUTH:
case BLOCK_FACE_WEST:
{
// When placing onto a sideways face, check cursor, if in top half, make it an upside-down stairs block
if (a_CursorY < 8)
{
a_BlockMeta |= 0x4;
}
break;
}
}
return true;
} }
// TODO: step sound // TODO: step sound
} ; } ;

View File

@ -19,20 +19,26 @@ public:
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
if (!TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_Dir)) // Find proper placement. Use the player-supplied one as the default, but fix if not okay:
if (!TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
{ {
a_Dir = FindSuitableDirection(a_World, a_BlockX, a_BlockY, a_BlockZ); a_BlockFace = FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ);
if (a_Dir == BLOCK_FACE_BOTTOM) if (a_BlockFace == BLOCK_FACE_BOTTOM)
{ {
return; return false;
} }
} }
a_BlockType = m_BlockType;
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, cTorch::DirectionToMetaData(a_Dir)); a_BlockMeta = cTorch::DirectionToMetaData(a_BlockFace);
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir); return true;
} }
@ -61,25 +67,25 @@ public:
} }
static bool TorchCanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) static bool TorchCanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{ {
// TODO: If placing a torch from below, check all 4 XZ neighbors, place it on that neighbor instead // TODO: If placing a torch from below, check all 4 XZ neighbors, place it on that neighbor instead
// How to propagate that change up? // How to propagate that change up?
// Simon: The easiest way is to calculate the position two times, shouldn´t cost much cpu power :) // Simon: The easiest way is to calculate the position two times, shouldn´t cost much cpu power :)
if (a_Dir == BLOCK_FACE_BOTTOM) if (a_BlockFace == BLOCK_FACE_BOTTOM)
{ {
return false; return false;
} }
AddDirection( a_BlockX, a_BlockY, a_BlockZ, a_Dir, true ); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true);
return CanBePlacedOn(a_World->GetBlock( a_BlockX, a_BlockY, a_BlockZ ), a_Dir); return CanBePlacedOn(a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ), a_BlockFace);
} }
/// Finds a suitable Direction for the Torch. Returns BLOCK_FACE_BOTTOM on failure /// Finds a suitable Face for the Torch. Returns BLOCK_FACE_BOTTOM on failure
static char FindSuitableDirection(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) static char FindSuitableFace(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ)
{ {
for (int i = 1; i <= 5; i++) for (int i = 1; i <= 5; i++)
{ {
@ -92,19 +98,21 @@ public:
} }
virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
{
if (TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
{ {
if(TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, a_Dir))
return true; return true;
}
return FindSuitableDirection(a_World, a_BlockX, a_BlockY, a_BlockZ) != BLOCK_FACE_BOTTOM; return (FindSuitableFace(a_World, a_BlockX, a_BlockY, a_BlockZ) != BLOCK_FACE_BOTTOM);
} }
virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override virtual bool CanBeAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
{ {
char Dir = cTorch::MetaDataToDirection(a_World->GetBlockMeta( a_BlockX, a_BlockY, a_BlockZ)); char Face = cTorch::MetaDataToDirection(a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ));
return TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, Dir); return TorchCanBePlacedAt(a_World, a_BlockX, a_BlockY, a_BlockZ, Face);
} }

View File

@ -18,18 +18,24 @@ public:
} }
virtual void PlaceBlock(cWorld * a_World, cPlayer * a_Player, NIBBLETYPE a_BlockMeta, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, cVine::DirectionToMetaData(a_Dir)); a_BlockType = m_BlockType;
OnPlacedByPlayer(a_World, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_Dir); a_BlockMeta = cVine::DirectionToMetaData(a_BlockFace);
return true;
} }
virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool CanBePlacedAt(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
{ {
if ( if (
(a_World->GetBlock( a_BlockX, a_BlockY + 1, a_BlockZ ) == E_BLOCK_VINES) && (a_World->GetBlock( a_BlockX, a_BlockY + 1, a_BlockZ ) == E_BLOCK_VINES) &&
(cVine::MetaDataToDirection(a_World->GetBlockMeta( a_BlockX, a_BlockY + 1, a_BlockZ )) == a_Dir) (cVine::MetaDataToDirection(a_World->GetBlockMeta(a_BlockX, a_BlockY + 1, a_BlockZ)) == a_BlockFace)
) )
{ {
return true; return true;
@ -38,17 +44,17 @@ public:
BLOCKTYPE TopBlock = a_World->GetBlock( a_BlockX, a_BlockY + 1, a_BlockZ); BLOCKTYPE TopBlock = a_World->GetBlock( a_BlockX, a_BlockY + 1, a_BlockZ);
if (g_BlockIsSolid[TopBlock] || (TopBlock == E_BLOCK_LEAVES)) if (g_BlockIsSolid[TopBlock] || (TopBlock == E_BLOCK_LEAVES))
{ {
AddDirection( a_BlockX, a_BlockY, a_BlockZ, a_Dir, true ); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true);
BLOCKTYPE BaseBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); BLOCKTYPE BaseBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (!g_BlockIsSolid[BaseBlock] && (BaseBlock != E_BLOCK_LEAVES)) if (!g_BlockIsSolid[BaseBlock] && (BaseBlock != E_BLOCK_LEAVES))
{ {
AddDirection( a_BlockX, a_BlockY, a_BlockZ, a_Dir, false ); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, false);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_VINES, 0); a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_VINES, 0);
} }
return true; return true;
} }
AddDirection( a_BlockX, a_BlockY, a_BlockZ, a_Dir, true ); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, true);
BLOCKTYPE BaseBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); BLOCKTYPE BaseBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
return (g_BlockIsSolid[BaseBlock] || (BaseBlock == E_BLOCK_LEAVES)); return (g_BlockIsSolid[BaseBlock] || (BaseBlock == E_BLOCK_LEAVES));
} }

View File

@ -19,7 +19,7 @@ public:
} }
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) override virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override
{ {
cWindow * Window = new cCraftingWindow(a_BlockX, a_BlockY, a_BlockZ); cWindow * Window = new cCraftingWindow(a_BlockX, a_BlockY, a_BlockZ);
a_Player->OpenWindow(Window); a_Player->OpenWindow(Window);

View File

@ -128,8 +128,6 @@ public:
int GetPosZ() { return m_PosZ; } int GetPosZ() { return m_PosZ; }
cWorld * GetWorld() { return m_World; } cWorld * GetWorld() { return m_World; }
// OBSOLETE void SendTo( cClientHandle * a_Client );
void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ); void SetBlock(int a_RelX, int a_RelY, int a_RelZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta );
// SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense // SetBlock() does a lot of work (heightmap, tickblocks, blockentities) so a BlockIdx version doesn't make sense
void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta ); } void SetBlock( const Vector3i & a_RelBlockPos, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta ) { SetBlock( a_RelBlockPos.x, a_RelBlockPos.y, a_RelBlockPos.z, a_BlockType, a_BlockMeta ); }

View File

@ -89,8 +89,8 @@ cClientHandle::cClientHandle(const cSocket * a_Socket, int a_ViewDistance)
, m_LastStreamedChunkZ(0x7fffffff) , m_LastStreamedChunkZ(0x7fffffff)
, m_ShouldCheckDownloaded(false) , m_ShouldCheckDownloaded(false)
, m_UniqueID(0) , m_UniqueID(0)
, m_BlockDigAnim(-1) , m_BlockDigAnimStage(-1)
, m_LastDigStatus(-1) , m_HasStartedDigging(false)
{ {
m_Protocol = new cProtocolRecognizer(this); m_Protocol = new cProtocolRecognizer(this);
@ -231,7 +231,7 @@ void cClientHandle::Authenticate(void)
m_Player->SetIP (m_IPString); m_Player->SetIP (m_IPString);
cRoot::Get()->GetPluginManager()->CallHook(cPluginManager::HOOK_PLAYER_JOIN, 1, m_Player); cRoot::Get()->GetPluginManager()->CallHookPlayerJoined(*m_Player);
m_ConfirmPosition = m_Player->GetPosition(); m_ConfirmPosition = m_Player->GetPosition();
@ -260,7 +260,7 @@ void cClientHandle::Authenticate(void)
// Broadcast this player's spawning to all other players in the same chunk // Broadcast this player's spawning to all other players in the same chunk
m_Player->GetWorld()->BroadcastSpawn(*m_Player, this); m_Player->GetWorld()->BroadcastSpawn(*m_Player, this);
cRoot::Get()->GetPluginManager()->CallHook(cPluginManager::HOOK_PLAYER_SPAWN, 1, m_Player); cRoot::Get()->GetPluginManager()->CallHookPlayerSpawned(*m_Player);
} }
@ -501,97 +501,142 @@ void cClientHandle::HandlePlayerPos(double a_PosX, double a_PosY, double a_PosZ,
void cClientHandle::HandleBlockDig(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status)
{ {
if (!CheckBlockInteractionsRate()) LOGD("HandleLeftClick: {%i, %i, %i}; Face: %i; Stat: %i",
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status
);
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
if (PlgMgr->CallHookPlayerLeftClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status))
{ {
// A plugin doesn't agree with the action, replace the block on the client and quit:
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
return; return;
} }
LOGD("OnBlockDig: {%i, %i, %i}; Face: %i; Stat: %i LastStat: %i", if (!CheckBlockInteractionsRate())
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status, m_LastDigStatus
);
// Do we want plugins to disable tossing items? Probably no, so toss item before asking plugins for permission
if (a_Status == DIG_STATUS_DROP_HELD) // Drop held item
{ {
// Too many interactions per second, simply ignore. Probably a hacked client, so don't even send bak the block
return;
}
switch (a_Status)
{
case DIG_STATUS_DROP_HELD: // Drop held item
{
if (PlgMgr->CallHookPlayerTossingItem(*m_Player))
{
// A plugin doesn't agree with the tossing. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return;
}
m_Player->TossItem(false); m_Player->TossItem(false);
return; return;
} }
if (a_Status == DIG_STATUS_SHOOT_EAT) case DIG_STATUS_SHOOT_EAT:
{ {
LOGINFO("BlockDig: Status SHOOT/EAT not implemented"); cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem());
if (ItemHandler->IsFood())
{
if (PlgMgr->CallHookPlayerEating(*m_Player))
{
// A plugin doesn't agree with the action. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return; return;
} }
cWorld * World = m_Player->GetWorld();
BLOCKTYPE OldBlock;
NIBBLETYPE OldMeta;
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, OldBlock, OldMeta);
if (cRoot::Get()->GetPluginManager()->CallHookBlockDig(m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status, OldBlock, OldMeta))
{
// The plugin doesn't agree with the digging, replace the block on the client and quit:
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
return;
}
bool bBroken = (
((a_Status == DIG_STATUS_FINISHED) &&
//Don't allow to finish digging if not started yet:
(m_LastDigStatus == 0) &&
(m_LastDigX == a_BlockX) &&
(m_LastDigY == a_BlockY) &&
(m_LastDigZ == a_BlockZ)) ||
(g_BlockOneHitDig[(int)OldBlock]) ||
((a_Status == DIG_STATUS_STARTED) && (m_Player->GetGameMode() == 1))
);
m_LastDigStatus = a_Status;
m_LastDigX = a_BlockX;
m_LastDigY = a_BlockY;
m_LastDigZ = a_BlockZ;
if ((a_Status == DIG_STATUS_STARTED) && (m_Player->GetGameMode() != eGameMode_Creative))
{
// Start dig animation
// TODO: calculate real animation speed
m_BlockDigAnimSpeed = 10;
m_BlockDigX = a_BlockX;
m_BlockDigY = a_BlockY;
m_BlockDigZ = a_BlockZ;
m_BlockDigAnim = 0;
m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigX, m_BlockDigY, m_BlockDigZ, 0, this);
}
else if (m_BlockDigAnim != -1)
{
// End dig animation
m_BlockDigAnim = -1;
// It seems that 10 ends block animation
m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigX, m_BlockDigY, m_BlockDigZ, 10, this);
}
cItem & Equipped = m_Player->GetInventory().GetEquippedItem();
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(Equipped.m_ItemID);
if (bBroken)
{
if(World->GetBlock(a_BlockX, a_BlockY, a_BlockZ) != E_BLOCK_AIR)
{
ItemHandler->OnBlockDestroyed(World, m_Player, &Equipped, a_BlockX, a_BlockY, a_BlockZ);
BlockHandler(OldBlock)->OnDestroyedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
World->BroadcastSoundParticleEffect(2001, a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, OldBlock, this);
World->DigBlock(a_BlockX, a_BlockY, a_BlockZ);
}
} }
else else
{ {
cBlockHandler * Handler = cBlockHandler::GetBlockHandler(OldBlock); if (PlgMgr->CallHookPlayerShooting(*m_Player))
{
// A plugin doesn't agree with the action. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
return;
}
}
LOGINFO("%s: Status SHOOT / EAT not implemented", __FUNCTION__);
return;
}
case DIG_STATUS_STARTED:
{
BLOCKTYPE OldBlock;
NIBBLETYPE OldMeta;
m_Player->GetWorld()->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, OldBlock, OldMeta);
HandleBlockDigStarted(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, OldBlock, OldMeta);
return;
}
case DIG_STATUS_FINISHED:
{
BLOCKTYPE OldBlock;
NIBBLETYPE OldMeta;
m_Player->GetWorld()->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, OldBlock, OldMeta);
HandleBlockDigFinished(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, OldBlock, OldMeta);
return;
}
default:
{
ASSERT(!"Unhandled DIG_STATUS");
return;
}
} // switch (a_Status)
}
void cClientHandle::HandleBlockDigStarted(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta)
{
if (
m_HasStartedDigging &&
(a_BlockX == m_LastDigBlockX) &&
(a_BlockY == m_LastDigBlockY) &&
(a_BlockZ == m_LastDigBlockZ)
)
{
// It is a duplicate packet, drop it right away
return;
}
if (cRoot::Get()->GetPluginManager()->CallHookPlayerBreakingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_OldBlock, a_OldMeta))
{
// A plugin doesn't agree with the breaking. Bail out. Send the block back to the client, so that it knows:
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
return;
}
// Set the last digging coords to the block being dug, so that they can be checked in DIG_FINISHED to avoid dig/aim bug in the client:
m_HasStartedDigging = true;
m_LastDigBlockX = a_BlockX;
m_LastDigBlockY = a_BlockY;
m_LastDigBlockZ = a_BlockZ;
// In creative mode, digging is done immediately
if (m_Player->GetGameMode() == eGameMode_Creative)
{
HandleBlockDigFinished(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_OldBlock, a_OldMeta);
return;
}
// Start dig animation
// TODO: calculate real animation speed
// TODO: Send animation packets even without receiving any other packets
m_BlockDigAnimSpeed = 10;
m_BlockDigAnimX = a_BlockX;
m_BlockDigAnimY = a_BlockY;
m_BlockDigAnimZ = a_BlockZ;
m_BlockDigAnimStage = 0;
m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigAnimX, m_BlockDigAnimY, m_BlockDigAnimZ, 0, this);
cWorld * World = m_Player->GetWorld();
cBlockHandler * Handler = cBlockHandler::GetBlockHandler(a_OldBlock);
Handler->OnDigging(World, m_Player, a_BlockX, a_BlockY, a_BlockZ); Handler->OnDigging(World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
ItemHandler->OnDiggingBlock(World, m_Player, &Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem());
ItemHandler->OnDiggingBlock(World, m_Player, &m_Player->GetEquippedItem(), a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
// Check for clickthrough-blocks: // Check for clickthrough-blocks:
if (a_BlockFace != BLOCK_FACE_NONE) if (a_BlockFace != BLOCK_FACE_NONE)
@ -599,27 +644,89 @@ void cClientHandle::HandleBlockDig(int a_BlockX, int a_BlockY, int a_BlockZ, cha
int pX = a_BlockX; int pX = a_BlockX;
int pY = a_BlockY; int pY = a_BlockY;
int pZ = a_BlockZ; int pZ = a_BlockZ;
AddDirection(pX, pY, pZ, a_BlockFace); AddFaceDirection(pX, pY, pZ, a_BlockFace);
Handler = cBlockHandler::GetBlockHandler(World->GetBlock(pX, pY, pZ)); Handler = cBlockHandler::GetBlockHandler(World->GetBlock(pX, pY, pZ));
// 2013_01_05 _X: This looks weird
// Why do we ask the block "behind" the one being clicked if it is clicked through? Shouldn't we ask the primary block instead?
if (Handler->IsClickedThrough()) if (Handler->IsClickedThrough())
{ {
Handler->OnDigging(World, m_Player, pX, pY, pZ); Handler->OnDigging(World, m_Player, pX, pY, pZ);
} }
} }
} }
void cClientHandle::HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta)
{
if (
!m_HasStartedDigging || // Hasn't received the DIG_STARTED packet
(m_LastDigBlockX != a_BlockX) || // DIG_STARTED has had different pos
(m_LastDigBlockY != a_BlockY) ||
(m_LastDigBlockZ != a_BlockZ)
)
{
LOGD("Prevented a dig/aim bug in the client (finish {%d, %d, %d} vs start {%d, %d, %d}, HSD: %s)",
a_BlockX, a_BlockY, a_BlockZ,
m_LastDigBlockX, m_LastDigBlockY, m_LastDigBlockZ,
m_HasStartedDigging
);
return;
}
m_HasStartedDigging = false;
if (m_BlockDigAnimStage != -1)
{
// End dig animation
m_BlockDigAnimStage = -1;
// It seems that 10 ends block animation
m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigAnimX, m_BlockDigAnimY, m_BlockDigAnimZ, 10, this);
}
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(m_Player->GetEquippedItem());
if (a_OldBlock == E_BLOCK_AIR)
{
LOGD("Digged air? wtf?");
return;
}
cWorld * World = m_Player->GetWorld();
ItemHandler->OnBlockDestroyed(World, m_Player, &m_Player->GetEquippedItem(), a_BlockX, a_BlockY, a_BlockZ);
BlockHandler(a_OldBlock)->OnDestroyedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
World->BroadcastSoundParticleEffect(2001, a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, a_OldBlock, this);
World->DigBlock(a_BlockX, a_BlockY, a_BlockZ);
cRoot::Get()->GetPluginManager()->CallHookPlayerBrokenBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_OldBlock, a_OldMeta);
} }
void cClientHandle::HandleBlockPlace(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, const cItem & a_HeldItem) void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem)
{ {
LOGD("HandleBlockPlace: {%d, %d, %d}, face %d, HeldItem: %s", LOGD("HandleRightClick: {%d, %d, %d}, face %d, HeldItem: %s",
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, ItemToFullString(a_HeldItem).c_str() a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, ItemToFullString(a_HeldItem).c_str()
); );
cPluginManager * PlgMgr = cRoot::Get()->GetPluginManager();
if (PlgMgr->CallHookPlayerRightClick(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
{
// A plugin doesn't agree with the action, replace the block on the client and quit:
if (a_BlockFace > -1)
{
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
}
return;
}
if (!CheckBlockInteractionsRate()) if (!CheckBlockInteractionsRate())
{ {
LOGD("Too many block interactions, aborting placement"); LOGD("Too many block interactions, aborting placement");
@ -640,7 +747,7 @@ void cClientHandle::HandleBlockPlace(int a_BlockX, int a_BlockY, int a_BlockZ, c
// Let's send the current world block to the client, so that it can immediately "let the user know" that they haven't placed the block // Let's send the current world block to the client, so that it can immediately "let the user know" that they haven't placed the block
if (a_BlockFace > -1) if (a_BlockFace > -1)
{ {
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
} }
return; return;
@ -648,95 +755,33 @@ void cClientHandle::HandleBlockPlace(int a_BlockX, int a_BlockY, int a_BlockZ, c
cWorld * World = m_Player->GetWorld(); cWorld * World = m_Player->GetWorld();
cBlockHandler *Handler = cBlockHandler::GetBlockHandler(World->GetBlock(a_BlockX, a_BlockY, a_BlockZ)); BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
cBlockHandler * Handler = cBlockHandler::GetBlockHandler(BlockType);
// TODO: Wrap following if into another if which will call hook 'OnBlockUse' (or some nicer name)
if (Handler->IsUseable()) if (Handler->IsUseable())
{ {
Handler->OnUse(World, m_Player, a_BlockX, a_BlockY, a_BlockZ); if (PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
} {
else // A plugin doesn't agree with using the block, abort
{ return;
cItemHandler * ItemHandler = cItemHandler::GetItemHandler(Equipped.m_ItemID);
if (ItemHandler->OnItemUse(World, m_Player, &Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
{
// Nothing here :P
}
else if (ItemHandler->IsPlaceable())
{
if (cRoot::Get()->GetPluginManager()->CallHookBlockPlace(m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, Equipped))
{
if (a_BlockFace > -1)
{
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
m_Player->GetWorld()->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
} }
Handler->OnUse(World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ);
PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
return; return;
} }
if (a_BlockFace < 0) cItemHandler * ItemHandler = cItemHandler::GetItemHandler(Equipped.m_ItemType);
if (ItemHandler->IsPlaceable())
{ {
// clicked in air HandlePlaceBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, *ItemHandler);
return;
}
BLOCKTYPE ClickedBlock = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
cBlockHandler *Handler = cBlockHandler::GetBlockHandler(ClickedBlock);
if (Handler->DoesIgnoreBuildCollision())
{
Handler->OnDestroyedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
// World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
}
else
{
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
// Check for Blocks not allowing placement on top
if ((a_BlockFace == BLOCK_FACE_TOP) && !Handler->DoesAllowBlockOnTop())
{
// Resend the old block
// Some times the client still places the block O.o
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
return;
}
BLOCKTYPE PlaceBlock = m_Player->GetWorld()->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision())
{
// Tried to place a block *into* another?
return; // Happens when you place a block aiming at side of block like torch or stem
}
}
cBlockHandler * NewBlock = BlockHandler(ItemHandler->GetBlockType());
// Cannot be placed on the side of an other block
if ((a_BlockFace != BLOCK_FACE_TOP) && !NewBlock->CanBePlacedOnSide())
{
return;
}
if (NewBlock->CanBePlacedAt(World, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace))
{
ItemHandler->PlaceBlock(World, m_Player, &m_Player->GetInventory().GetEquippedItem(), a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
// Step sound with 0.8f pitch is used as block placement sound
World->BroadcastSoundEffect(NewBlock->GetStepSound(),a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.8f);
}
else
{
LOGD("Block refused placement here, aborting");
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player); // Send the old block back to the player
return;
}
} }
else if (ItemHandler->IsFood()) else if (ItemHandler->IsFood())
{ {
cItem Item; cItem Item;
Item.m_ItemID = Equipped.m_ItemID; Item.m_ItemType = Equipped.m_ItemType;
Item.m_ItemCount = 1; Item.m_ItemCount = 1;
if (ItemHandler->EatItem(m_Player, &Item)) if (ItemHandler->EatItem(m_Player, &Item))
{ {
@ -745,7 +790,98 @@ void cClientHandle::HandleBlockPlace(int a_BlockX, int a_BlockY, int a_BlockZ, c
return; return;
} }
} }
else
{
if (PlgMgr->CallHookPlayerUsingItem(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
{
// A plugin doesn't agree with using the item, abort
return;
} }
ItemHandler->OnItemUse(World, m_Player, &Equipped, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
PlgMgr->CallHookPlayerUsedItem(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ);
}
}
void cClientHandle::HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, cItemHandler & a_ItemHandler)
{
if (a_BlockFace < 0)
{
// Clicked in air
return;
}
cWorld * World = m_Player->GetWorld();
// Check if the block ignores build collision (water, grass etc.):
BLOCKTYPE ClickedBlock = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
cBlockHandler * Handler = cBlockHandler::GetBlockHandler(ClickedBlock);
if (Handler->DoesIgnoreBuildCollision())
{
Handler->OnDestroyedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ);
// World->FastSetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_AIR, 0);
}
else
{
AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
// Check for Blocks not allowing placement on top
if ((a_BlockFace == BLOCK_FACE_TOP) && !Handler->DoesAllowBlockOnTop())
{
// Resend the old block
// Some times the client still places the block O.o
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
return;
}
BLOCKTYPE PlaceBlock = World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
if (!BlockHandler(PlaceBlock)->DoesIgnoreBuildCollision())
{
// Tried to place a block *into* another?
return; // Happens when you place a block aiming at side of block like torch or stem
}
}
BLOCKTYPE BlockType;
NIBBLETYPE BlockMeta;
if (!a_ItemHandler.GetPlacementBlockTypeMeta(World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
{
// Handler refused the placement, send that information back to the client:
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockY, m_Player);
return;
}
cBlockHandler * NewBlock = BlockHandler(BlockType);
if ((a_BlockFace != BLOCK_FACE_TOP) && !NewBlock->CanBePlacedOnSide())
{
// Cannot be placed on the side of an other block
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
return;
}
if (cRoot::Get()->GetPluginManager()->CallHookPlayerPlacingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
{
// A plugin doesn't agree with placing the block, revert the block on the client:
World->SendBlockTo(a_BlockX, a_BlockY, a_BlockZ, m_Player);
return;
}
// The actual block placement:
World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
if (m_Player->GetGameMode() == eGameMode_Survival)
{
cItem Item(m_Player->GetEquippedItem().m_ItemType, 1);
m_Player->GetInventory().RemoveItem(Item);
}
NewBlock->OnPlacedByPlayer(World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
// Step sound with 0.8f pitch is used as block placement sound
World->BroadcastSoundEffect(NewBlock->GetStepSound(),a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 1.0f, 0.8f);
cRoot::Get()->GetPluginManager()->CallHookPlayerPlacedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
} }
@ -951,7 +1087,7 @@ void cClientHandle::HandleRespawn(void)
return; return;
} }
m_Player->Respawn(); m_Player->Respawn();
cRoot::Get()->GetPluginManager()->CallHook(cPluginManager::HOOK_PLAYER_SPAWN, 1, m_Player); cRoot::Get()->GetPluginManager()->CallHookPlayerSpawned(*m_Player);
} }
@ -1129,17 +1265,17 @@ void cClientHandle::Tick(float a_Dt)
} }
// Handle block break animation: // Handle block break animation:
if ((m_Player != NULL) && (m_BlockDigAnim > -1)) if ((m_Player != NULL) && (m_BlockDigAnimStage > -1))
{ {
int lastAnimVal = m_BlockDigAnim; int lastAnimVal = m_BlockDigAnimStage;
m_BlockDigAnim += (int)(m_BlockDigAnimSpeed * a_Dt); m_BlockDigAnimStage += (int)(m_BlockDigAnimSpeed * a_Dt);
if (m_BlockDigAnim > 9000) if (m_BlockDigAnimStage > 9000)
{ {
m_BlockDigAnim = 9000; m_BlockDigAnimStage = 9000;
} }
if (m_BlockDigAnim / 1000 != lastAnimVal / 1000) if (m_BlockDigAnimStage / 1000 != lastAnimVal / 1000)
{ {
m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigX, m_BlockDigY, m_BlockDigZ, (char)(m_BlockDigAnim / 1000), this); m_Player->GetWorld()->BroadcastBlockBreakAnimation(m_UniqueID, m_BlockDigAnimX, m_BlockDigAnimY, m_BlockDigAnimZ, (char)(m_BlockDigAnimStage / 1000), this);
} }
} }
} }
@ -1626,7 +1762,7 @@ void cClientHandle::SendConfirmPosition(void)
m_State = csConfirmingPos; m_State = csConfirmingPos;
if (!cRoot::Get()->GetPluginManager()->CallHook(cPluginManager::HOOK_PLAYER_JOIN, 1, m_Player)) if (!cRoot::Get()->GetPluginManager()->CallHookPlayerJoined(*m_Player))
{ {
// Broadcast that this player has joined the game! Yay~ // Broadcast that this player has joined the game! Yay~
cRoot::Get()->GetServer()->BroadcastChat(m_Username + " joined the game!", this); cRoot::Get()->GetServer()->BroadcastChat(m_Username + " joined the game!", this);

View File

@ -31,6 +31,7 @@ class cProtocol;
class cRedstone; class cRedstone;
class cWindow; class cWindow;
class cFallingBlock; class cFallingBlock;
class cItemHandler;
@ -150,8 +151,8 @@ public:
void HandlePing (void); void HandlePing (void);
void HandleCreativeInventory(short a_SlotNum, const cItem & a_HeldItem); void HandleCreativeInventory(short a_SlotNum, const cItem & a_HeldItem);
void HandlePlayerPos (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround); void HandlePlayerPos (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, bool a_IsOnGround);
void HandleBlockDig (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status); void HandleLeftClick (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
void HandleBlockPlace (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, const cItem & a_HeldItem); void HandleRightClick (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, const cItem & a_HeldItem);
void HandleChat (const AString & a_Message); void HandleChat (const AString & a_Message);
void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround); void HandlePlayerLook (float a_Rotation, float a_Pitch, bool a_IsOnGround);
void HandlePlayerMoveLook (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround); // While m_bPositionConfirmed (normal gameplay) void HandlePlayerMoveLook (double a_PosX, double a_PosY, double a_PosZ, double a_Stance, float a_Rotation, float a_Pitch, bool a_IsOnGround); // While m_bPositionConfirmed (normal gameplay)
@ -221,16 +222,17 @@ private:
static const unsigned short PING_TIME_MS = 1000; //minecraft sends 1 per 20 ticks (1 second or every 1000 ms) static const unsigned short PING_TIME_MS = 1000; //minecraft sends 1 per 20 ticks (1 second or every 1000 ms)
// Values required for block dig animation // Values required for block dig animation
int m_BlockDigAnim; // Current stage of the animation; -1 if not digging int m_BlockDigAnimStage; // Current stage of the animation; -1 if not digging
int m_BlockDigAnimSpeed; // Current speed of the animation (units ???) int m_BlockDigAnimSpeed; // Current speed of the animation (units ???)
int m_BlockDigX; int m_BlockDigAnimX;
int m_BlockDigY; int m_BlockDigAnimY;
int m_BlockDigZ; int m_BlockDigAnimZ;
char m_LastDigStatus; // To avoid dig/aim bug in the client, store the last position given in a DIG_START packet and compare to that when processing the DIG_FINISH packet:
int m_LastDigX; bool m_HasStartedDigging;
int m_LastDigY; int m_LastDigBlockX;
int m_LastDigZ; int m_LastDigBlockY;
int m_LastDigBlockZ;
enum eState enum eState
{ {
@ -264,6 +266,15 @@ private:
/// Adds a single chunk to be streamed to the client; used by StreamChunks() /// Adds a single chunk to be streamed to the client; used by StreamChunks()
void StreamChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ); void StreamChunk(int a_ChunkX, int a_ChunkY, int a_ChunkZ);
/// Handles the DIG_STARTED dig packet:
void HandleBlockDigStarted (int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta);
/// Handles the DIG_FINISHED dig packet:
void HandleBlockDigFinished(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta);
/// Handles the block placing packet when it is a real block placement (not block-using, item-using or eating)
void HandlePlaceBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, cItemHandler & a_ItemHandler);
// cSocketThreads::cCallback overrides: // cSocketThreads::cCallback overrides:
virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client
virtual void GetOutgoingData(AString & a_Data) override; // Data can be sent to client virtual void GetOutgoingData(AString & a_Data) override; // Data can be sent to client

View File

@ -148,10 +148,10 @@ void cCraftingGrid::ConsumeGrid(const cCraftingGrid & a_Grid)
continue; continue;
} }
int ThisIdx = x + m_Width * y; int ThisIdx = x + m_Width * y;
if (a_Grid.m_Items[ThatIdx].m_ItemID != m_Items[ThisIdx].m_ItemID) if (a_Grid.m_Items[ThatIdx].m_ItemType != m_Items[ThisIdx].m_ItemType)
{ {
LOGWARNING("Consuming incompatible grids: item at (%d, %d) is %d in grid and %d in ingredients. Item not consumed.", LOGWARNING("Consuming incompatible grids: item at (%d, %d) is %d in grid and %d in ingredients. Item not consumed.",
x, y, m_Items[ThisIdx].m_ItemID, a_Grid.m_Items[ThatIdx].m_ItemID x, y, m_Items[ThisIdx].m_ItemType, a_Grid.m_Items[ThatIdx].m_ItemType
); );
continue; continue;
} }
@ -159,7 +159,7 @@ void cCraftingGrid::ConsumeGrid(const cCraftingGrid & a_Grid)
if (NumWantedItems > m_Items[ThisIdx].m_ItemCount) if (NumWantedItems > m_Items[ThisIdx].m_ItemCount)
{ {
LOGWARNING("Consuming more items than there actually are in slot (%d, %d), item %d (want %d, have %d). Item zeroed out.", LOGWARNING("Consuming more items than there actually are in slot (%d, %d), item %d (want %d, have %d). Item zeroed out.",
x, y, m_Items[ThisIdx].m_ItemID, x, y, m_Items[ThisIdx].m_ItemType,
NumWantedItems, m_Items[ThisIdx].m_ItemCount NumWantedItems, m_Items[ThisIdx].m_ItemCount
); );
NumWantedItems = m_Items[ThisIdx].m_ItemCount; NumWantedItems = m_Items[ThisIdx].m_ItemCount;
@ -194,7 +194,7 @@ void cCraftingGrid::Dump(void)
{ {
int idx = x + m_Width * y; int idx = x + m_Width * y;
LOGD("Slot (%d, %d): Type %d, health %d, count %d", LOGD("Slot (%d, %d): Type %d, health %d, count %d",
x, y, m_Items[idx].m_ItemID, m_Items[idx].m_ItemHealth, m_Items[idx].m_ItemCount x, y, m_Items[idx].m_ItemType, m_Items[idx].m_ItemDamage, m_Items[idx].m_ItemCount
); );
} }
} }
@ -248,7 +248,7 @@ void cCraftingRecipe::Dump(void)
LOGD("Recipe ingredients:"); LOGD("Recipe ingredients:");
m_Ingredients.Dump(); m_Ingredients.Dump();
LOGD("Result: Type %d, health %d, count %d", LOGD("Result: Type %d, health %d, count %d",
m_Result.m_ItemID, m_Result.m_ItemHealth, m_Result.m_ItemCount m_Result.m_ItemType, m_Result.m_ItemDamage, m_Result.m_ItemCount
); );
} }
@ -438,8 +438,8 @@ bool cCraftingRecipes::ParseItem(const AString & a_String, cItem & a_Item)
if (Split.size() > 1) if (Split.size() > 1)
{ {
AString Damage = TrimString(Split[1]); AString Damage = TrimString(Split[1]);
a_Item.m_ItemHealth = atoi(Damage.c_str()); a_Item.m_ItemDamage = atoi(Damage.c_str());
if ((a_Item.m_ItemHealth == 0) && (Damage.compare("0") != 0)) if ((a_Item.m_ItemDamage == 0) && (Damage.compare("0") != 0))
{ {
// Parsing the number failed // Parsing the number failed
return false; return false;
@ -662,11 +662,11 @@ cCraftingRecipes::cRecipe * cCraftingRecipes::MatchRecipe(const cItem * a_Crafti
if ( if (
(itrS->x >= a_GridWidth) || (itrS->x >= a_GridWidth) ||
(itrS->y >= a_GridHeight) || (itrS->y >= a_GridHeight) ||
(itrS->m_Item.m_ItemID != a_CraftingGrid[GridID].m_ItemID) || // same item type? (itrS->m_Item.m_ItemType != a_CraftingGrid[GridID].m_ItemType) || // same item type?
(itrS->m_Item.m_ItemCount > a_CraftingGrid[GridID].m_ItemCount) || // not enough items (itrS->m_Item.m_ItemCount > a_CraftingGrid[GridID].m_ItemCount) || // not enough items
( (
(itrS->m_Item.m_ItemHealth > 0) && // should compare damage values? (itrS->m_Item.m_ItemDamage > 0) && // should compare damage values?
(itrS->m_Item.m_ItemHealth != a_CraftingGrid[GridID].m_ItemHealth) (itrS->m_Item.m_ItemDamage != a_CraftingGrid[GridID].m_ItemDamage)
) )
) )
{ {
@ -711,10 +711,10 @@ cCraftingRecipes::cRecipe * cCraftingRecipes::MatchRecipe(const cItem * a_Crafti
} }
int GridIdx = x + a_GridStride * y; int GridIdx = x + a_GridStride * y;
if ( if (
(a_CraftingGrid[GridIdx].m_ItemID == itrS->m_Item.m_ItemID) && (a_CraftingGrid[GridIdx].m_ItemType == itrS->m_Item.m_ItemType) &&
( (
(itrS->m_Item.m_ItemHealth < 0) || // doesn't want damage comparison (itrS->m_Item.m_ItemDamage < 0) || // doesn't want damage comparison
(itrS->m_Item.m_ItemHealth == a_CraftingGrid[GridIdx].m_ItemHealth) // the damage matches (itrS->m_Item.m_ItemDamage == a_CraftingGrid[GridIdx].m_ItemDamage) // the damage matches
) )
) )
{ {

View File

@ -6,16 +6,18 @@
typedef unsigned char Byte; typedef unsigned char Byte;
// tolua_begin // tolua_begin
// emissive blocks
extern unsigned char g_BlockLightValue[];
// whether blocks allow spreading
extern unsigned char g_BlockSpreadLightFalloff[];
// whether blocks are transparent (light can shine though)
extern bool g_BlockTransparent[];
// one hit break blocks
extern bool g_BlockOneHitDig[];
//--DO NOT DELETE THIS COMMENT-- //tolua_export /// How much light do the blocks emit on their own?
extern unsigned char g_BlockLightValue[];
/// How much light do the block consume?
extern unsigned char g_BlockSpreadLightFalloff[];
/// Is a block completely transparent? (light doesn't get decreased(?))
extern bool g_BlockTransparent[];
/// Is a block destroyed after a single hit?
extern bool g_BlockOneHitDig[];
@ -49,12 +51,12 @@ enum
inline bool IsValidBlock(int a_BlockType) // tolua_export inline bool IsValidBlock(int a_BlockType) // tolua_export
{ // tolua_export { // tolua_export
if( a_BlockType > -1 && if (
a_BlockType <= 145 && //items to 109 are valid for Beta1.8.1.. 1.2.5 is up to 126 (a_BlockType > -1) &&
//a_BlockType != 29 && allow pistons (a_BlockType <= E_BLOCK_MAX_TYPE_ID) &&
//a_BlockType != 33 && allow pistons (a_BlockType != 34) && // Piston extension
a_BlockType != 34 && (a_BlockType != 36) // Piston moved block
a_BlockType != 36 ) )
{ {
return true; return true;
} }
@ -65,20 +67,22 @@ inline bool IsValidBlock( int a_BlockType ) //tolua_export
// Was old :o inline bool IsValidItem(int a_ItemType) // tolua_export
// Changed to fit the style ;)
inline bool IsValidItem( int a_ItemID ) //tolua_export
{ // tolua_export { // tolua_export
if( (a_ItemID >= 256 && a_ItemID <= 400) if (
|| (a_ItemID >= 2256 && a_ItemID <= 2267) ) ((a_ItemType >= E_ITEM_FIRST) && (a_ItemType <= E_ITEM_MAX_CONSECUTIVE_TYPE_ID)) || // Basic items range
((a_ItemType >= E_ITEM_FIRST_DISC) && (a_ItemType <= E_ITEM_LAST_DISC)) // Music discs' special range
)
{ {
return true; return true;
} }
if( a_ItemID == 0 ) if (a_ItemType == 0)
{
return false; return false;
}
return IsValidBlock( a_ItemID ); return IsValidBlock(a_ItemType);
} // tolua_export } // tolua_export
@ -87,7 +91,7 @@ inline bool IsValidItem( int a_ItemID ) //tolua_export
inline bool IsBlockWater(BLOCKTYPE a_BlockType) inline bool IsBlockWater(BLOCKTYPE a_BlockType)
{ {
return (a_BlockType == E_BLOCK_WATER || a_BlockType == E_BLOCK_STATIONARY_WATER); return ((a_BlockType == E_BLOCK_WATER) || (a_BlockType == E_BLOCK_STATIONARY_WATER));
} }
@ -96,15 +100,22 @@ inline bool IsBlockWater(BLOCKTYPE a_BlockType)
inline bool IsBlockLava(BLOCKTYPE a_BlockType) inline bool IsBlockLava(BLOCKTYPE a_BlockType)
{ {
return (a_BlockType == E_BLOCK_LAVA || a_BlockType == E_BLOCK_STATIONARY_LAVA); return ((a_BlockType == E_BLOCK_LAVA) || (a_BlockType == E_BLOCK_STATIONARY_LAVA));
} }
inline bool IsBlockLiquid(BLOCKTYPE a_BlockType) inline bool IsBlockLiquid(BLOCKTYPE a_BlockType)
{ {
return IsBlockWater(a_BlockType) || IsBlockLava(a_BlockType); return IsBlockWater(a_BlockType) || IsBlockLava(a_BlockType);
} }
inline bool IsBlockTypeOfDirt(BLOCKTYPE a_BlockType) inline bool IsBlockTypeOfDirt(BLOCKTYPE a_BlockType)
{ {
switch (a_BlockType) switch (a_BlockType)
@ -112,71 +123,82 @@ inline bool IsBlockTypeOfDirt(BLOCKTYPE a_BlockType)
case E_BLOCK_DIRT: case E_BLOCK_DIRT:
case E_BLOCK_GRASS: case E_BLOCK_GRASS:
case E_BLOCK_FARMLAND: case E_BLOCK_FARMLAND:
{
return true; return true;
} }
}
return false; return false;
} }
inline void AddDirection( int & a_X, int & a_Y, int & a_Z, char a_Direction, bool a_bInverse = false ) inline void AddFaceDirection(int & a_BlockX, int & a_BlockY, int & a_BlockZ, char a_BlockFace, bool a_bInverse = false) // tolua_export
{ { // tolua_export
if (!a_bInverse) if (!a_bInverse)
{ {
switch (a_Direction) switch (a_BlockFace)
{ {
case BLOCK_FACE_BOTTOM: a_Y--; break; case BLOCK_FACE_BOTTOM: a_BlockY--; break;
case BLOCK_FACE_TOP: a_Y++; break; case BLOCK_FACE_TOP: a_BlockY++; break;
case BLOCK_FACE_EAST: a_X++; break; case BLOCK_FACE_EAST: a_BlockX++; break;
case BLOCK_FACE_WEST: a_X--; break; case BLOCK_FACE_WEST: a_BlockX--; break;
case BLOCK_FACE_NORTH: a_Z--; break; case BLOCK_FACE_NORTH: a_BlockZ--; break;
case BLOCK_FACE_SOUTH: a_Z++; break; case BLOCK_FACE_SOUTH: a_BlockZ++; break;
default: default:
{ {
LOGWARNING("AddDirection(): Unknown direction: %d", a_Direction); LOGWARNING("%s: Unknown face: %d", __FUNCTION__, a_BlockFace);
ASSERT(!"AddDirection(): Unknown direction"); ASSERT(!"AddFaceDirection(): Unknown face");
break; break;
} }
} }
} }
else else
{ {
switch( a_Direction ) // other way around switch (a_BlockFace)
{ {
case BLOCK_FACE_BOTTOM: a_Y++; break; case BLOCK_FACE_BOTTOM: a_BlockY++; break;
case BLOCK_FACE_TOP: a_Y--; break; case BLOCK_FACE_TOP: a_BlockY--; break;
case BLOCK_FACE_EAST: a_X--; break; case BLOCK_FACE_EAST: a_BlockX--; break;
case BLOCK_FACE_WEST: a_X++; break; case BLOCK_FACE_WEST: a_BlockX++; break;
case BLOCK_FACE_NORTH: a_Z++; break; case BLOCK_FACE_NORTH: a_BlockZ++; break;
case BLOCK_FACE_SOUTH: a_Z--; break; case BLOCK_FACE_SOUTH: a_BlockZ--; break;
default: default:
{ {
LOGWARNING("AddDirection(): Unknown inv direction: %d", a_Direction); LOGWARNING("%s: Unknown inv face: %d", __FUNCTION__, a_BlockFace);
ASSERT(!"AddDirection(): Unknown direction"); ASSERT(!"AddFaceDirection(): Unknown face");
break; break;
} }
} }
} }
}
inline void AddDirection( int & a_X, unsigned char & a_Y, int & a_Z, char a_Direction, bool a_bInverse = false ) //tolua_export
{//tolua_export
int Y = a_Y;
AddDirection( a_X, Y, a_Z, a_Direction, a_bInverse );
if( Y < 0 ) a_Y = 0;
else if( Y > 255 ) a_Y = 255;
else a_Y = (unsigned char)Y;
} // tolua_export } // tolua_export
inline void AddFaceDirection(int & a_BlockX, unsigned char & a_BlockY, int & a_BlockZ, char a_BlockFace, bool a_bInverse = false)
{
int Y = a_BlockY;
AddFaceDirection(a_BlockX, Y, a_BlockZ, a_BlockFace, a_bInverse);
if (Y < 0)
{
a_BlockY = 0;
}
else if (Y > 255)
{
a_BlockY = 255;
}
else
{
a_BlockY = (unsigned char)Y;
}
}
#include <math.h> #include <math.h>
#define PI 3.14159265358979323846264338327950288419716939937510582097494459072381640628620899862803482534211706798f #define PI 3.14159265358979323846264338327950288419716939937510582097494459072381640628620899862803482534211706798f
#define MIN(a,b) (((a)>(b))?(b):(a)) #define MIN(a,b) (((a)>(b))?(b):(a))

View File

@ -121,7 +121,7 @@ void cDispenserEntity::Dispense()
else else
{ {
cItems Pickups; cItems Pickups;
Pickups.push_back(cItem(Drop.m_ItemType, 1, Drop.m_ItemHealth)); Pickups.push_back(cItem(Drop.m_ItemType, 1, Drop.m_ItemDamage));
m_World->SpawnItemPickups(Pickups, Disp_X, Disp_Y, Disp_Z); m_World->SpawnItemPickups(Pickups, Disp_X, Disp_Y, Disp_Z);
m_Items[OccupiedSlots[RandomSlot]].m_ItemCount--; m_Items[OccupiedSlots[RandomSlot]].m_ItemCount--;
} }
@ -138,7 +138,7 @@ void cDispenserEntity::Dispense()
else else
{ {
cItems Pickups; cItems Pickups;
Pickups.push_back(cItem(Drop.m_ItemType, 1, Drop.m_ItemHealth)); Pickups.push_back(cItem(Drop.m_ItemType, 1, Drop.m_ItemDamage));
m_World->SpawnItemPickups(Pickups, Disp_X, Disp_Y, Disp_Z); m_World->SpawnItemPickups(Pickups, Disp_X, Disp_Y, Disp_Z);
m_Items[OccupiedSlots[RandomSlot]].m_ItemCount--; m_Items[OccupiedSlots[RandomSlot]].m_ItemCount--;
} }
@ -155,7 +155,7 @@ void cDispenserEntity::Dispense()
else else
{ {
cItems Pickups; cItems Pickups;
Pickups.push_back(cItem(Drop.m_ItemType, 1, Drop.m_ItemHealth)); Pickups.push_back(cItem(Drop.m_ItemType, 1, Drop.m_ItemDamage));
m_World->SpawnItemPickups(Pickups, Disp_X, Disp_Y, Disp_Z); m_World->SpawnItemPickups(Pickups, Disp_X, Disp_Y, Disp_Z);
m_Items[OccupiedSlots[RandomSlot]].m_ItemCount--; m_Items[OccupiedSlots[RandomSlot]].m_ItemCount--;
} }
@ -172,7 +172,7 @@ void cDispenserEntity::Dispense()
default: default:
{ {
cItems Pickups; cItems Pickups;
Pickups.push_back(cItem(Drop.m_ItemType, 1, Drop.m_ItemHealth)); Pickups.push_back(cItem(Drop.m_ItemType, 1, Drop.m_ItemDamage));
m_World->SpawnItemPickups(Pickups, Disp_X, Disp_Y, Disp_Z); m_World->SpawnItemPickups(Pickups, Disp_X, Disp_Y, Disp_Z);
m_Items[OccupiedSlots[RandomSlot]].m_ItemCount--; m_Items[OccupiedSlots[RandomSlot]].m_ItemCount--;
break; break;
@ -280,9 +280,9 @@ bool cDispenserEntity::LoadFromFile(cFile & f)
for(unsigned int i = 0; i < NumSlots; i++) for(unsigned int i = 0; i < NumSlots; i++)
{ {
cItem & Item = m_Items[i]; cItem & Item = m_Items[i];
READ(f, Item.m_ItemID); READ(f, Item.m_ItemType);
READ(f, Item.m_ItemCount); READ(f, Item.m_ItemCount);
READ(f, Item.m_ItemHealth); READ(f, Item.m_ItemDamage);
} }
return true; return true;

View File

@ -138,8 +138,8 @@ bool cFurnaceEntity::Tick( float a_Dt )
m_Items[0].m_ItemCount--; m_Items[0].m_ItemCount--;
if( m_Items[0].IsEmpty() ) m_Items[0].Empty(); if( m_Items[0].IsEmpty() ) m_Items[0].Empty();
m_Items[2].m_ItemHealth = m_CookingItem->m_ItemHealth; m_Items[2].m_ItemDamage = m_CookingItem->m_ItemDamage;
m_Items[2].m_ItemID = m_CookingItem->m_ItemID; m_Items[2].m_ItemType = m_CookingItem->m_ItemType;
m_Items[2].m_ItemCount += m_CookingItem->m_ItemCount; m_Items[2].m_ItemCount += m_CookingItem->m_ItemCount;
delete m_CookingItem; delete m_CookingItem;
m_CookingItem = NULL; m_CookingItem = NULL;
@ -299,14 +299,14 @@ bool cFurnaceEntity::LoadFromFile(cFile & f)
for(unsigned int i = 0; i < NumSlots; i++) for(unsigned int i = 0; i < NumSlots; i++)
{ {
cItem & Item = m_Items[i]; cItem & Item = m_Items[i];
READ(f, Item.m_ItemID); READ(f, Item.m_ItemType);
READ(f, Item.m_ItemCount); READ(f, Item.m_ItemCount);
READ(f, Item.m_ItemHealth); READ(f, Item.m_ItemDamage);
} }
cItem CookingItem; cItem CookingItem;
READ(f, CookingItem.m_ItemID); READ(f, CookingItem.m_ItemType);
READ(f, CookingItem.m_ItemCount); READ(f, CookingItem.m_ItemCount);
READ(f, CookingItem.m_ItemHealth); READ(f, CookingItem.m_ItemDamage);
if (!CookingItem.IsEmpty()) if (!CookingItem.IsEmpty())
{ {
m_CookingItem = new cItem(CookingItem); m_CookingItem = new cItem(CookingItem);

View File

@ -204,7 +204,7 @@ const cFurnaceRecipe::Recipe* cFurnaceRecipe::GetRecipeFrom( const cItem & a_Ing
for( RecipeList::const_iterator itr = m_pState->Recipes.begin(); itr != m_pState->Recipes.end(); ++itr ) for( RecipeList::const_iterator itr = m_pState->Recipes.begin(); itr != m_pState->Recipes.end(); ++itr )
{ {
const Recipe & R = *itr; const Recipe & R = *itr;
if( (R.In->m_ItemID == a_Ingredient.m_ItemID) && (R.In->m_ItemCount <= a_Ingredient.m_ItemCount ) ) if( (R.In->m_ItemType == a_Ingredient.m_ItemType) && (R.In->m_ItemCount <= a_Ingredient.m_ItemCount ) )
{ {
if( BestRecipe && (BestRecipe->In->m_ItemCount > R.In->m_ItemCount) ) if( BestRecipe && (BestRecipe->In->m_ItemCount > R.In->m_ItemCount) )
{ {
@ -225,7 +225,7 @@ float cFurnaceRecipe::GetBurnTime( const cItem & a_Fuel ) const
for( FuelList::const_iterator itr = m_pState->Fuel.begin(); itr != m_pState->Fuel.end(); ++itr ) for( FuelList::const_iterator itr = m_pState->Fuel.begin(); itr != m_pState->Fuel.end(); ++itr )
{ {
const Fuel & F = *itr; const Fuel & F = *itr;
if( (F.In->m_ItemID == a_Fuel.m_ItemID) && (F.In->m_ItemCount <= a_Fuel.m_ItemCount ) ) if( (F.In->m_ItemType == a_Fuel.m_ItemType) && (F.In->m_ItemCount <= a_Fuel.m_ItemCount ) )
{ {
if( BestFuel > 0.f && (BestFuel > F.BurnTime ) ) if( BestFuel > 0.f && (BestFuel > F.BurnTime ) )
{ {

View File

@ -597,7 +597,7 @@ void cChunkGenerator::DoGenerate(int a_ChunkX, int a_ChunkY, int a_ChunkZ)
true true
); );
cRoot::Get()->GetPluginManager()->CallHook(cPluginManager::E_PLUGIN_CHUNK_GENERATED, 3, m_World, a_ChunkX, a_ChunkZ); cRoot::Get()->GetPluginManager()->CallHookChunkGenerated(m_World, a_ChunkX, a_ChunkZ);
} }

View File

@ -12,16 +12,19 @@
typedef std::map< AString, cGroup* > GroupMap; typedef std::map< AString, cGroup* > GroupMap;
struct cGroupManager::sGroupManagerState struct cGroupManager::sGroupManagerState
{ {
GroupMap Groups; GroupMap Groups;
}; };
cGroupManager* cGroupManager::GetGroupManager()
{
LOGWARN("WARNING: Using deprecated function cGroupManager::GetGroupManager() use cRoot::Get()->GetGroupManager() instead!");
return cRoot::Get()->GetGroupManager();
}
cGroupManager::~cGroupManager() cGroupManager::~cGroupManager()
{ {
@ -34,6 +37,10 @@ cGroupManager::~cGroupManager()
delete m_pState; delete m_pState;
} }
cGroupManager::cGroupManager() cGroupManager::cGroupManager()
: m_pState( new sGroupManagerState ) : m_pState( new sGroupManagerState )
{ {
@ -98,6 +105,10 @@ cGroupManager::cGroupManager()
LOG("-- Done Loading Groups --"); LOG("-- Done Loading Groups --");
} }
cGroup* cGroupManager::GetGroup( const AString & a_Name ) cGroup* cGroupManager::GetGroup( const AString & a_Name )
{ {
GroupMap::iterator itr = m_pState->Groups.find( a_Name ); GroupMap::iterator itr = m_pState->Groups.find( a_Name );
@ -110,5 +121,8 @@ cGroup* cGroupManager::GetGroup( const AString & a_Name )
m_pState->Groups[a_Name] = Group; m_pState->Groups[a_Name] = Group;
return Group; return Group;
} }

View File

@ -1,12 +1,21 @@
#pragma once #pragma once
class cGroup; class cGroup;
class cGroupManager class cGroupManager
{ {
public: public:
static cGroupManager * GetGroupManager(); //tolua_export
cGroup * GetGroup(const AString & a_Name); cGroup * GetGroup(const AString & a_Name);
private: private:
friend class cRoot; friend class cRoot;
cGroupManager(); cGroupManager();
@ -15,3 +24,7 @@ private:
struct sGroupManagerState; struct sGroupManagerState;
sGroupManagerState * m_pState; sGroupManagerState * m_pState;
} ; } ;

View File

@ -77,7 +77,7 @@ bool cInventory::AddItem( cItem & a_Item )
{ {
if (ChangedSlots[i]) if (ChangedSlots[i])
{ {
LOGD("cInventory::AddItem(): Item was added to %i ID:%i Count:%i", i, m_Slots[i].m_ItemID, m_Slots[i].m_ItemCount); LOGD("cInventory::AddItem(): Item was added to %i ID:%i Count:%i", i, m_Slots[i].m_ItemType, m_Slots[i].m_ItemCount);
SendSlot(i); SendSlot(i);
} }
} }
@ -107,7 +107,7 @@ bool cInventory::AddItemAnyAmount( cItem & a_Item )
{ {
if (ChangedSlots[i]) if (ChangedSlots[i])
{ {
LOGD("cInventory::AddItemAnyAmount(): Item was added to %i ID:%i Count:%i", i, m_Slots[i].m_ItemID, m_Slots[i].m_ItemCount); LOGD("cInventory::AddItemAnyAmount(): Item was added to %i ID:%i Count:%i", i, m_Slots[i].m_ItemType, m_Slots[i].m_ItemCount);
SendSlot(i); SendSlot(i);
} }
} }
@ -125,7 +125,7 @@ bool cInventory::RemoveItem( cItem & a_Item )
// First check equipped slot // First check equipped slot
if ((m_EquippedSlot >= 0) && (m_EquippedSlot < 9)) if ((m_EquippedSlot >= 0) && (m_EquippedSlot < 9))
{ {
if (m_HotSlots[m_EquippedSlot].m_ItemID == a_Item.m_ItemID) if (m_HotSlots[m_EquippedSlot].m_ItemType == a_Item.m_ItemType)
{ {
cItem & Item = m_HotSlots[m_EquippedSlot]; cItem & Item = m_HotSlots[m_EquippedSlot];
if(Item.m_ItemCount > a_Item.m_ItemCount) if(Item.m_ItemCount > a_Item.m_ItemCount)
@ -149,7 +149,7 @@ bool cInventory::RemoveItem( cItem & a_Item )
for(int i = 0; i < 36; i++) for(int i = 0; i < 36; i++)
{ {
cItem & Item = m_MainSlots[i]; cItem & Item = m_MainSlots[i];
if( Item.m_ItemID == a_Item.m_ItemID ) if( Item.m_ItemType == a_Item.m_ItemType )
{ {
if(Item.m_ItemCount > a_Item.m_ItemCount) if(Item.m_ItemCount > a_Item.m_ItemCount)
{ {
@ -323,7 +323,7 @@ int cInventory::HowManyCanFit(short a_ItemType, short a_ItemDamage, int a_BeginS
{ {
if ( if (
m_Slots[i].IsEmpty() || m_Slots[i].IsEmpty() ||
((m_Slots[i].m_ItemID == a_ItemType) && (m_Slots[i].m_ItemHealth == a_ItemDamage)) ((m_Slots[i].m_ItemType == a_ItemType) && (m_Slots[i].m_ItemDamage == a_ItemDamage))
) )
{ {
int MaxCount = ItemHandler(a_ItemType)->GetMaxStackSize(); int MaxCount = ItemHandler(a_ItemType)->GetMaxStackSize();
@ -345,15 +345,15 @@ int cInventory::MoveItem(short a_ItemType, short a_ItemDamage, int a_Count, int
{ {
if ( if (
m_Slots[i].IsEmpty() || m_Slots[i].IsEmpty() ||
((m_Slots[i].m_ItemID == a_ItemType) && (m_Slots[i].m_ItemHealth == a_ItemDamage)) ((m_Slots[i].m_ItemType == a_ItemType) && (m_Slots[i].m_ItemDamage == a_ItemDamage))
) )
{ {
int MaxCount = ItemHandler(a_ItemType)->GetMaxStackSize(); int MaxCount = ItemHandler(a_ItemType)->GetMaxStackSize();
ASSERT(m_Slots[i].m_ItemCount <= MaxCount); ASSERT(m_Slots[i].m_ItemCount <= MaxCount);
int NumToMove = std::min(a_Count, MaxCount - m_Slots[i].m_ItemCount); int NumToMove = std::min(a_Count, MaxCount - m_Slots[i].m_ItemCount);
m_Slots[i].m_ItemCount += NumToMove; m_Slots[i].m_ItemCount += NumToMove;
m_Slots[i].m_ItemHealth = a_ItemDamage; m_Slots[i].m_ItemDamage = a_ItemDamage;
m_Slots[i].m_ItemID = a_ItemType; m_Slots[i].m_ItemType = a_ItemType;
SendSlot(i); SendSlot(i);
res += NumToMove; res += NumToMove;
a_Count -= NumToMove; a_Count -= NumToMove;
@ -380,7 +380,7 @@ bool cInventory::AddToBar( cItem & a_Item, const int a_Offset, const int a_Size,
int MaxStackSize = cItemHandler::GetItemHandler(a_Item.m_ItemType)->GetMaxStackSize(); int MaxStackSize = cItemHandler::GetItemHandler(a_Item.m_ItemType)->GetMaxStackSize();
for(int i = 0; i < a_Size; i++) for(int i = 0; i < a_Size; i++)
{ {
if( m_Slots[i + a_Offset].m_ItemType == a_Item.m_ItemType && m_Slots[i + a_Offset].m_ItemCount < MaxStackSize && m_Slots[i + a_Offset].m_ItemHealth == a_Item.m_ItemHealth ) if( m_Slots[i + a_Offset].m_ItemType == a_Item.m_ItemType && m_Slots[i + a_Offset].m_ItemCount < MaxStackSize && m_Slots[i + a_Offset].m_ItemDamage == a_Item.m_ItemDamage )
{ {
int NumFree = MaxStackSize - m_Slots[i + a_Offset].m_ItemCount; int NumFree = MaxStackSize - m_Slots[i + a_Offset].m_ItemCount;
if( NumFree >= a_Item.m_ItemCount ) if( NumFree >= a_Item.m_ItemCount )

View File

@ -10,21 +10,21 @@
void cItem::GetJson( Json::Value & a_OutValue ) const void cItem::GetJson( Json::Value & a_OutValue ) const
{ {
a_OutValue["ID"] = m_ItemID; a_OutValue["ID"] = m_ItemType;
if( m_ItemID > 0 ) if( m_ItemType > 0 )
{ {
a_OutValue["Count"] = m_ItemCount; a_OutValue["Count"] = m_ItemCount;
a_OutValue["Health"] = m_ItemHealth; a_OutValue["Health"] = m_ItemDamage;
} }
} }
void cItem::FromJson( const Json::Value & a_Value ) void cItem::FromJson( const Json::Value & a_Value )
{ {
m_ItemID = (ENUM_ITEM_ID)a_Value.get("ID", -1 ).asInt(); m_ItemType = (ENUM_ITEM_ID)a_Value.get("ID", -1 ).asInt();
if( m_ItemID > 0 ) if( m_ItemType > 0 )
{ {
m_ItemCount = (char)a_Value.get("Count", -1 ).asInt(); m_ItemCount = (char)a_Value.get("Count", -1 ).asInt();
m_ItemHealth = (short)a_Value.get("Health", -1 ).asInt(); m_ItemDamage = (short)a_Value.get("Health", -1 ).asInt();
} }
} }

View File

@ -16,48 +16,51 @@ namespace Json
class cItem class cItem
{ {
public: public:
cItem(short a_ItemType = E_ITEM_EMPTY, char a_ItemCount = 0, short a_ItemHealth = 0) cItem(short a_ItemType = E_ITEM_EMPTY, char a_ItemCount = 0, short a_ItemDamage = 0)
: m_ItemType (a_ItemType) : m_ItemType (a_ItemType)
, m_ItemCount (a_ItemCount) , m_ItemCount (a_ItemCount)
, m_ItemHealth(a_ItemHealth) , m_ItemDamage(a_ItemDamage)
{ {
if (!IsValidItem( m_ItemID ) ) m_ItemID = E_ITEM_EMPTY; if (!IsValidItem(m_ItemType))
{
m_ItemType = E_ITEM_EMPTY;
}
} }
void Empty() void Empty()
{ {
m_ItemID = E_ITEM_EMPTY; m_ItemType = E_ITEM_EMPTY;
m_ItemCount = 0; m_ItemCount = 0;
m_ItemHealth = 0; m_ItemDamage = 0;
} }
void Clear(void) void Clear(void)
{ {
m_ItemID = E_ITEM_EMPTY; m_ItemType = E_ITEM_EMPTY;
m_ItemCount = 0; m_ItemCount = 0;
m_ItemHealth = 0; m_ItemDamage = 0;
} }
bool IsEmpty(void) const bool IsEmpty(void) const
{ {
return (m_ItemID <= 0 || m_ItemCount <= 0); return (m_ItemType <= 0 || m_ItemCount <= 0);
} }
bool IsEqual(const cItem & a_Item) const bool IsEqual(const cItem & a_Item) const
{ {
return (IsSameType(a_Item) && (m_ItemHealth == a_Item.m_ItemHealth)); return (IsSameType(a_Item) && (m_ItemDamage == a_Item.m_ItemDamage));
} }
bool IsSameType(const cItem & a_Item) const bool IsSameType(const cItem & a_Item) const
{ {
return (m_ItemID == a_Item.m_ItemID) || (IsEmpty() && a_Item.IsEmpty()); return (m_ItemType == a_Item.m_ItemType) || (IsEmpty() && a_Item.IsEmpty());
} }
// TODO Sorry for writing the functions in the header. But somehow it doesn´t worked when I put them into the cpp File :s // TODO Sorry for writing the functions in the header. But somehow it doesn´t worked when I put them into the cpp File :s
inline int GetMaxDuration(void) const inline int GetMaxDuration(void) const
{ {
switch(m_ItemID) switch (m_ItemType)
{ {
case 256: return 251; case 256: return 251;
case 257: return 251; case 257: return 251;
@ -90,13 +93,13 @@ public:
} }
} }
// Damages a weapon / tool. Returns true when destroyed /// Damages a weapon / tool. Returns true when destroyed
inline bool DamageItem() inline bool DamageItem()
{ {
if (HasDuration()) if (HasDuration())
{ {
m_ItemHealth++; m_ItemDamage++;
if(m_ItemHealth >= GetMaxDuration()) if (m_ItemDamage >= GetMaxDuration())
return true; return true;
} }
return false; return false;
@ -111,23 +114,9 @@ public:
static bool IsEnchantable(short a_ItemType); static bool IsEnchantable(short a_ItemType);
// tolua_end
union
{
// tolua_begin
short m_ItemID; // OBSOLETE, use m_ItemType instead
short m_ItemType; short m_ItemType;
// tolua_end char m_ItemCount;
} ;
char m_ItemCount; // tolua_export
union
{
// tolua_begin
short m_ItemHealth; // OBSOLETE, use m_ItemDamage instead
short m_ItemDamage; short m_ItemDamage;
// tolua_end
} ;
// tolua_begin
}; };
// tolua_end // tolua_end

View File

@ -3,23 +3,54 @@
#include "ItemHandler.h" #include "ItemHandler.h"
#include "../World.h" #include "../World.h"
#include "../Blocks/BlockBed.h"
class cItemBedHandler : public cItemHandler
class cItemBedHandler :
public cItemHandler
{ {
public: public:
cItemBedHandler(int a_ItemType) cItemBedHandler(int a_ItemType) :
: cItemHandler(a_ItemType) cItemHandler(a_ItemType)
{ {
} }
virtual bool IsPlaceable() override
virtual bool IsPlaceable(void) override
{ {
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
return E_BLOCK_BED; if (a_BlockFace != BLOCK_FACE_TOP)
{
// Can only be placed on the floor
return false;
}
a_BlockMeta = cBlockBedHandler::RotationToMetaData(a_Player->GetRotation());
// Check if there is empty space for the foot section:
Vector3i Direction = cBlockBedHandler::MetaDataToDirection(a_BlockMeta);
if (a_World->GetBlock(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z) != E_BLOCK_AIR)
{
return false;
}
a_BlockType = E_BLOCK_BED;
return true;
} }
} ; } ;

View File

@ -3,23 +3,39 @@
#include "ItemHandler.h" #include "ItemHandler.h"
class cItemBrewingStandHandler : public cItemHandler
class cItemBrewingStandHandler :
public cItemHandler
{ {
public: public:
cItemBrewingStandHandler(int a_ItemType) cItemBrewingStandHandler(int a_ItemType) :
: cItemHandler(a_ItemType) cItemHandler(a_ItemType)
{ {
} }
virtual bool IsPlaceable() override
virtual bool IsPlaceable(void) override
{ {
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override
{
return E_BLOCK_BREWING_STAND;
}
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
a_BlockType = E_BLOCK_BREWING_STAND;
a_BlockMeta = 0;
return true;
}
} ; } ;

View File

@ -37,13 +37,13 @@ public:
bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) bool ScoopUpFluid(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
{ {
if (a_Dir < 0) if (a_BlockFace < 0)
{ {
return false; return false;
} }
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
BLOCKTYPE ClickedBlock; BLOCKTYPE ClickedBlock;
NIBBLETYPE ClickedMeta; NIBBLETYPE ClickedMeta;
a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedMeta); a_World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, ClickedBlock, ClickedMeta);
@ -100,9 +100,9 @@ public:
} }
bool PlaceFluid(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir, BLOCKTYPE a_FluidBlock) bool PlaceFluid(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_FluidBlock)
{ {
if (a_Dir < 0) if (a_BlockFace < 0)
{ {
return false; return false;
} }
@ -112,7 +112,7 @@ public:
if (!CanWashAway) if (!CanWashAway)
{ {
// The block pointed at cannot be washed away, so put fluid on top of it / on its sides // The block pointed at cannot be washed away, so put fluid on top of it / on its sides
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ); CurrentBlock = a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ);
} }
if ( if (

View File

@ -3,23 +3,39 @@
#include "ItemHandler.h" #include "ItemHandler.h"
class cItemCauldronHandler : public cItemHandler
class cItemCauldronHandler :
public cItemHandler
{ {
public: public:
cItemCauldronHandler(int a_ItemType) cItemCauldronHandler(int a_ItemType) :
: cItemHandler(a_ItemType) cItemHandler(a_ItemType)
{ {
} }
virtual bool IsPlaceable() override
virtual bool IsPlaceable(void) override
{ {
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override
{
return E_BLOCK_CAULDRON;
}
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
a_BlockType = E_BLOCK_CAULDRON;
a_BlockMeta = 0;
return true;
}
} ; } ;

View File

@ -4,23 +4,42 @@
#include "ItemHandler.h" #include "ItemHandler.h"
#include "../World.h" #include "../World.h"
class cItemDoorHandler : public cItemHandler
class cItemDoorHandler :
public cItemHandler
{ {
public: public:
cItemDoorHandler(int a_ItemType) cItemDoorHandler(int a_ItemType) :
: cItemHandler(a_ItemType) cItemHandler(a_ItemType)
{ {
} }
virtual bool IsPlaceable() override virtual bool IsPlaceable(void) override
{ {
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
return (m_ItemType == E_ITEM_WOODEN_DOOR) ? E_BLOCK_WOODEN_DOOR : E_BLOCK_IRON_DOOR; a_BlockType = (m_ItemType == E_ITEM_WOODEN_DOOR) ? E_BLOCK_WOODEN_DOOR : E_BLOCK_IRON_DOOR;
return BlockHandler(a_BlockType)->GetPlacementBlockTypeMeta(
a_World, a_Player,
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
a_CursorX, a_CursorY, a_CursorZ,
a_BlockType, a_BlockMeta
);
} }
} ; } ;

View File

@ -23,13 +23,13 @@ public:
{ {
// TODO: Handle coloring the sheep, too (OnItemUseOnEntity maybe) // TODO: Handle coloring the sheep, too (OnItemUseOnEntity maybe)
// Handle growing the plants: // Handle growing the plants:
if (a_Item->m_ItemHealth == E_META_DYE_WHITE) if (a_Item->m_ItemDamage == E_META_DYE_WHITE)
{ {
if (a_World->GrowRipePlant(a_BlockX, a_BlockY, a_BlockZ, true)) if (a_World->GrowRipePlant(a_BlockX, a_BlockY, a_BlockZ, true))
{ {
if (a_Player->GetGameMode() != eGameMode_Creative) if (a_Player->GetGameMode() != eGameMode_Creative)
{ {
cItem Item(a_Item->m_ItemType, 1, a_Item->m_ItemHealth); cItem Item(a_Item->m_ItemType, 1, a_Item->m_ItemDamage);
a_Player->GetInventory().RemoveItem(Item); a_Player->GetInventory().RemoveItem(Item);
return true; return true;
} }

View File

@ -3,23 +3,39 @@
#include "ItemHandler.h" #include "ItemHandler.h"
class cItemFlowerPotHandler : public cItemHandler
class cItemFlowerPotHandler :
public cItemHandler
{ {
public: public:
cItemFlowerPotHandler(int a_ItemType) cItemFlowerPotHandler(int a_ItemType) :
: cItemHandler(a_ItemType) cItemHandler(a_ItemType)
{ {
} }
virtual bool IsPlaceable() override
virtual bool IsPlaceable(void) override
{ {
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override
{
return E_BLOCK_FLOWER_POT;
}
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{
a_BlockType = E_BLOCK_FLOWER_POT;
a_BlockMeta = 0;
return true;
}
} ; } ;

View File

@ -386,43 +386,31 @@ bool cItemHandler::CanHarvestBlock(BLOCKTYPE a_BlockType)
BLOCKTYPE cItemHandler::GetBlockType() bool cItemHandler::GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
)
{ {
ASSERT(m_ItemType < 256); // Items with IDs above 255 should all be handled by specific handlers ASSERT(m_ItemType < 256); // Items with IDs above 255 should all be handled by specific handlers
#ifdef _DEBUG
if (m_ItemType > 256) if (m_ItemType > 256)
{ {
LOGERROR("Item %d has no valid block!", m_ItemType); LOGERROR("%s: Item %d has no valid block!", __FUNCTION__, m_ItemType);
} return false;
#endif // _DEBUG
return (BLOCKTYPE) m_ItemType;
} }
cBlockHandler * BlockH = BlockHandler(m_ItemType);
return BlockH->GetPlacementBlockTypeMeta(
a_World, a_Player,
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
NIBBLETYPE cItemHandler::GetBlockMeta(short a_ItemDamage) a_CursorX, a_CursorY, a_CursorZ,
{ a_BlockType, a_BlockMeta
return (NIBBLETYPE)a_ItemDamage & 0x0f; // This keeps most textures. The few other items have to override this );
} a_BlockType = (BLOCKTYPE) m_ItemType;
a_BlockMeta = (NIBBLETYPE)(a_Player->GetEquippedItem().m_ItemDamage & 0x0f); // This keeps most textures. The few other items have to override this
return true;
void cItemHandler::PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir)
{
BLOCKTYPE Block = GetBlockType();
cBlockHandler *Handler = cBlockHandler::GetBlockHandler(Block);
Handler->PlaceBlock(a_World, a_Player, GetBlockMeta(a_Item->m_ItemHealth), a_BlockX, a_BlockY, a_BlockZ, a_Dir);
if(a_Player->GetGameMode() == eGameMode_Survival)
{
cItem Item(a_Item->m_ItemType, 1);
a_Player->GetInventory().RemoveItem(Item);
}
} }

View File

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "../Defines.h" #include "../Defines.h"
#include "../Item.h"
@ -18,13 +20,17 @@ class cItemHandler
{ {
public: public:
cItemHandler(int a_ItemType); cItemHandler(int a_ItemType);
// Called when the player tries to use the item. Return false to make the item unusable. DEFAULT: False
/// Called when the player tries to use the item. Return false to make the item unusable. DEFAULT: False
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir); //eg for fishing or hoes virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir); //eg for fishing or hoes
// Called while the player diggs a block using this item
/// Called while the player diggs a block using this item
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, cItem * a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace); virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, cItem * a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
// Called when the player destroys a block using this item. This also calls the drop function for the destroyed block
/// 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, cItem *a_Item, int a_X, int a_Y, int a_Z); virtual void OnBlockDestroyed(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_X, int a_Y, int a_Z);
// Called after the player has eaten this item.
/// Called after the player has eaten this item.
virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item); virtual void OnFoodEaten(cWorld *a_World, cPlayer *a_Player, cItem *a_Item);
/// Returns the maximum stack size for a given item /// Returns the maximum stack size for a given item
@ -43,34 +49,40 @@ public:
char PoisionChance; //0 - 100 char PoisionChance; //0 - 100
}; };
// Returns the FoodInfo for this item. (FoodRecovery, Saturation and PoisionChance) /// Returns the FoodInfo for this item. (FoodRecovery, Saturation and PoisionChance)
virtual FoodInfo GetFoodInfo(); virtual FoodInfo GetFoodInfo();
// Lets the player eat a selected item. Returns true if the player ate the item /// Lets the player eat a selected item. Returns true if the player ate the item
virtual bool EatItem(cPlayer *a_Player, cItem *a_Item); virtual bool EatItem(cPlayer *a_Player, cItem *a_Item);
// Places the current block and removes the item from the player inventory /// Indicates if this item is a tool
virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir); virtual bool IsTool(void);
// Indicates if this item is a tool /// Indicates if this item is food
virtual bool IsTool(); virtual bool IsFood(void);
// Indicates if this item is food
virtual bool IsFood();
//Blocks simply get placed
virtual bool IsPlaceable();
// Returns the block type on placement /// Blocks simply get placed
virtual BLOCKTYPE GetBlockType(); virtual bool IsPlaceable(void);
//Returns the block meta on placement
virtual NIBBLETYPE GetBlockMeta(short a_ItemDamage); /** Called before a block is placed into a world.
// Returns whether this tool/item can harvest a specific block (e.g. wooden pickaxe can harvest stone, but wood can´t) DEFAULT: False 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, char 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
virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType); virtual bool CanHarvestBlock(BLOCKTYPE a_BlockType);
static cItemHandler * GetItemHandler(int a_ItemType); static cItemHandler * GetItemHandler(int a_ItemType);
static cItemHandler * GetItemHandler(const cItem & a_Item) { return GetItemHandler(a_Item.m_ItemType); }
static void Deinit(); static void Deinit();
protected: protected:
int m_ItemType; int m_ItemType;
static cItemHandler *CreateItemHandler(int m_ItemType); static cItemHandler *CreateItemHandler(int m_ItemType);

View File

@ -10,15 +10,29 @@
class cItemLeavesHandler : class cItemLeavesHandler :
public cItemHandler public cItemHandler
{ {
typedef cItemHandler super;
public: public:
cItemLeavesHandler(int a_ItemType) cItemLeavesHandler(int a_ItemType)
: cItemHandler(a_ItemType) : cItemHandler(a_ItemType)
{ {
} }
virtual NIBBLETYPE GetBlockMeta(short a_ItemDamage) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
return (NIBBLETYPE)(a_ItemDamage & 0x0f) | 0x4; //0x4 bit set means this is a player-placed leaves block, not to be decayed bool res = super::GetPlacementBlockTypeMeta(
a_World, a_Player,
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
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
return res;
} }
} ; } ;

View File

@ -1,32 +1,40 @@
#pragma once #pragma once
#include "ItemHandler.h" #include "ItemHandler.h"
#include "../World.h" #include "../World.h"
#include "../Player.h" #include "../Player.h"
class cItemLighterHandler : public cItemHandler
class cItemLighterHandler :
public cItemHandler
{ {
public: public:
cItemLighterHandler(int a_ItemType) cItemLighterHandler(int a_ItemType) :
: cItemHandler(a_ItemType) cItemHandler(a_ItemType)
{ {
} }
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
{ {
if (a_Dir < 0) if (a_BlockFace < 0)
{ {
return false; return false;
} }
a_Player->UseEquippedItem(); a_Player->UseEquippedItem();
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0); //0 -> new fire TODO: Make Firesimulator use this a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_FIRE, 0); //0 -> new fire TODO: Make Firesimulator use this
return false; return false;
} }
} ; } ;

View File

@ -15,19 +15,21 @@ public:
{ {
} }
virtual bool IsPlaceable() override virtual bool IsPlaceable(void) override
{ {
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
return E_BLOCK_REDSTONE_WIRE; a_BlockType = E_BLOCK_REDSTONE_WIRE;
} a_BlockMeta = 0;
return true;
virtual NIBBLETYPE GetBlockMeta(short a_ItemDamage) override
{
return 0;
} }
} ; } ;

View File

@ -2,12 +2,14 @@
#pragma once #pragma once
#include "ItemHandler.h" #include "ItemHandler.h"
#include "../Simulator/RedstoneSimulator.h"
class cItemRedstoneRepeaterHandler : public cItemHandler class cItemRedstoneRepeaterHandler :
public cItemHandler
{ {
public: public:
cItemRedstoneRepeaterHandler(int a_ItemType) cItemRedstoneRepeaterHandler(int a_ItemType)
@ -20,14 +22,16 @@ public:
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
return ::E_BLOCK_REDSTONE_REPEATER_OFF; a_BlockType = E_BLOCK_REDSTONE_REPEATER_OFF;
} a_BlockMeta = cRedstoneSimulator::RepeaterRotationToMetaData(a_Player->GetRotation());
return true;
virtual NIBBLETYPE GetBlockMeta(short a_ItemMeta) override
{
return 0;
} }
} ; } ;

View File

@ -9,6 +9,8 @@
class cItemSaplingHandler : public cItemHandler class cItemSaplingHandler : public cItemHandler
{ {
typedef cItemHandler super;
public: public:
cItemSaplingHandler(int a_ItemType) cItemSaplingHandler(int a_ItemType)
: cItemHandler(a_ItemType) : cItemHandler(a_ItemType)
@ -16,10 +18,22 @@ public:
} }
virtual NIBBLETYPE GetBlockMeta(short a_ItemDamage) override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
bool res = super::GetPlacementBlockTypeMeta(
a_World, a_Player,
a_BlockX, a_BlockY, a_BlockZ, a_BlockFace,
a_CursorX, a_CursorY, a_CursorZ,
a_BlockType, a_BlockMeta
);
// Only the lowest 3 bits are important // Only the lowest 3 bits are important
return (NIBBLETYPE)(a_ItemDamage & 0x07); a_BlockMeta = a_BlockMeta & 0x7;
return res;
} }
} ; } ;

View File

@ -12,54 +12,49 @@ class cItemSeedsHandler :
public cItemHandler public cItemHandler
{ {
public: public:
cItemSeedsHandler(int a_ItemType) cItemSeedsHandler(int a_ItemType) :
: cItemHandler(a_ItemType) cItemHandler(a_ItemType)
{ {
} }
virtual bool IsPlaceable() override virtual bool IsPlaceable(void) override
{ {
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
switch(m_ItemType) if (a_BlockFace != BLOCK_FACE_TOP)
{
case E_ITEM_SEEDS: return E_BLOCK_CROPS;
case E_ITEM_MELON_SEEDS: return E_BLOCK_MELON_STEM;
case E_ITEM_PUMPKIN_SEEDS: return E_BLOCK_PUMPKIN_STEM;
default: return E_BLOCK_AIR;
}
}
virtual NIBBLETYPE GetBlockMeta(short a_ItemDamage) override
{
return 0; //Not grown yet
}
virtual void PlaceBlock(cWorld *a_World, cPlayer *a_Player, cItem *a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
{
if (a_Dir != BLOCK_FACE_TOP)
{ {
// Only allow planting seeds from the top side of the block // Only allow planting seeds from the top side of the block
return; return false;
} }
// Only allow placement on farmland
int X = a_BlockX; int X = a_BlockX;
int Y = a_BlockY; int Y = a_BlockY;
int Z = a_BlockZ; int Z = a_BlockZ;
AddFaceDirection(X, Y, Z, a_BlockFace, true);
AddDirection(X, Y, Z, a_Dir, true);
if (a_World->GetBlock(X, Y, Z) != E_BLOCK_FARMLAND) if (a_World->GetBlock(X, Y, Z) != E_BLOCK_FARMLAND)
{ {
return; return false;
} }
return cItemHandler::PlaceBlock(a_World, a_Player, a_Item, a_BlockX, a_BlockY, a_BlockZ, a_Dir); a_BlockMeta = 0;
switch (m_ItemType)
{
case E_ITEM_SEEDS: a_BlockType = E_BLOCK_CROPS; return true;
case E_ITEM_MELON_SEEDS: a_BlockType = E_BLOCK_MELON_STEM; return true;
case E_ITEM_PUMPKIN_SEEDS: a_BlockType = E_BLOCK_PUMPKIN_STEM; return true;
default: a_BlockType = E_BLOCK_AIR; return true;
}
return false;
} }
} ; } ;

View File

@ -3,24 +3,49 @@
#include "ItemHandler.h" #include "ItemHandler.h"
#include "../World.h" #include "../World.h"
#include "../Sign.h"
class cItemSignHandler : public cItemHandler
class cItemSignHandler :
public cItemHandler
{ {
public: public:
cItemSignHandler(int a_ItemType) cItemSignHandler(int a_ItemType) :
: cItemHandler(a_ItemType) cItemHandler(a_ItemType)
{ {
} }
virtual bool IsPlaceable() override
virtual bool IsPlaceable(void) override
{ {
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override
{
return E_BLOCK_SIGN_POST;
}
virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char 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 = cSign::RotationToMetaData(a_Player->GetRotation());
a_BlockType = E_BLOCK_SIGN_POST;
}
else
{
a_BlockMeta = cSign::DirectionToMetaData(a_BlockFace);
a_BlockType = E_BLOCK_WALLSIGN;
}
return true;
}
} ; } ;

View File

@ -27,7 +27,7 @@ public:
((a_Dir == 0) || (a_Dir == 1)) // Only when clicking on top or on bottom of the block ((a_Dir == 0) || (a_Dir == 1)) // Only when clicking on top or on bottom of the block
&& ((Block == E_BLOCK_WOODEN_SLAB) || (Block == E_BLOCK_STONE_SLAB)) // It is a slab && ((Block == E_BLOCK_WOODEN_SLAB) || (Block == E_BLOCK_STONE_SLAB)) // It is a slab
&& (Block == a_Item->m_ItemType) // Same slab && (Block == a_Item->m_ItemType) // Same slab
&& ((Meta & 0x7) == (a_Item->m_ItemHealth & 0x7))) // Same Texture && ((Meta & 0x7) == (a_Item->m_ItemDamage & 0x7))) // Same Texture
{ {
if (a_Player->GetGameMode() == eGameMode_Creative) if (a_Player->GetGameMode() == eGameMode_Creative)
{ {

View File

@ -19,16 +19,16 @@ public:
} }
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, cItem * a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
{ {
if (a_Dir < 0) if (a_BlockFace < 0)
{ {
return false; return false;
} }
AddDirection(a_BlockX, a_BlockY, a_BlockZ, a_Dir); AddFaceDirection(a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
if (a_Dir == BLOCK_FACE_BOTTOM) if (a_BlockFace == BLOCK_FACE_BOTTOM)
{ {
a_BlockY--; a_BlockY--;
} }

View File

@ -2,7 +2,6 @@
#pragma once #pragma once
#include "ItemHandler.h" #include "ItemHandler.h"
#include "../World.h"
@ -12,25 +11,26 @@ class cItemSugarcaneHandler :
public cItemHandler public cItemHandler
{ {
public: public:
cItemSugarcaneHandler(int a_ItemType) cItemSugarcaneHandler(int a_ItemType) :
: cItemHandler(a_ItemType) cItemHandler(a_ItemType)
{ {
} }
virtual bool IsPlaceable() override virtual bool IsPlaceable(void) override
{ {
return true; return true;
} }
virtual BLOCKTYPE GetBlockType() override virtual bool GetPlacementBlockTypeMeta(
cWorld * a_World, cPlayer * a_Player,
int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace,
int a_CursorX, int a_CursorY, int a_CursorZ,
BLOCKTYPE & a_BlockType, NIBBLETYPE & a_BlockMeta
) override
{ {
return E_BLOCK_SUGARCANE; a_BlockType = E_BLOCK_SUGARCANE;
} a_BlockMeta = 0;
return true;
virtual NIBBLETYPE GetBlockMeta(short a_ItemDamage) override
{
return 0; //Not grown yet
} }
} ; } ;

View File

@ -13,30 +13,46 @@
bool report_errors(lua_State * lua, int status) bool report_errors(lua_State * lua, int status)
{ {
if ( status!=0 ) if (status == 0)
{ {
std::string s = lua_tostring(lua, -1); // No error to report
LOGERROR("-- %s", s.c_str() ); return false;
}
LOGERROR("LUA: %s", lua_tostring(lua, -1));
lua_pop(lua, 1); lua_pop(lua, 1);
return true; return true;
} }
return false;
}
cLuaCommandBinder::cLuaCommandBinder() cLuaCommandBinder::cLuaCommandBinder()
{ {
} }
cLuaCommandBinder::~cLuaCommandBinder() cLuaCommandBinder::~cLuaCommandBinder()
{ {
} }
void cLuaCommandBinder::ClearBindings() void cLuaCommandBinder::ClearBindings()
{ {
m_BoundCommands.clear(); m_BoundCommands.clear();
} }
void cLuaCommandBinder::RemoveBindingsForPlugin( cPlugin* a_Plugin ) void cLuaCommandBinder::RemoveBindingsForPlugin( cPlugin* a_Plugin )
{ {
for( CommandMap::iterator itr = m_BoundCommands.begin(); itr != m_BoundCommands.end(); ) for( CommandMap::iterator itr = m_BoundCommands.begin(); itr != m_BoundCommands.end(); )
@ -54,6 +70,10 @@ void cLuaCommandBinder::RemoveBindingsForPlugin( cPlugin* a_Plugin )
} }
} }
bool cLuaCommandBinder::BindCommand( const std::string & a_Command, const std::string & a_Permission, cPlugin* a_Plugin, lua_State * a_LuaState, int a_FunctionReference ) bool cLuaCommandBinder::BindCommand( const std::string & a_Command, const std::string & a_Permission, cPlugin* a_Plugin, lua_State * a_LuaState, int a_FunctionReference )
{ {
if( !a_Plugin->CanBindCommands() ) if( !a_Plugin->CanBindCommands() )
@ -71,6 +91,10 @@ bool cLuaCommandBinder::BindCommand( const std::string & a_Command, const std::s
return true; return true;
} }
bool cLuaCommandBinder::HandleCommand( const std::string & a_Command, cPlayer* a_Player ) bool cLuaCommandBinder::HandleCommand( const std::string & a_Command, cPlayer* a_Player )
{ {
AStringVector Split = StringSplit(a_Command, " "); AStringVector Split = StringSplit(a_Command, " ");
@ -124,3 +148,7 @@ bool cLuaCommandBinder::HandleCommand( const std::string & a_Command, cPlayer* a
} }
return false; return false;
} }

View File

@ -20,17 +20,8 @@
static bool report_errors(lua_State* lua, int status) // fwd: LuaCommandBinder.cpp
{ bool report_errors(lua_State* lua, int status);
if ( status!=0 )
{
std::string s = lua_tostring(lua, -1);
LOGERROR("-- %s", s.c_str() );
lua_pop(lua, 1);
return true;
}
return false;
}

View File

@ -124,7 +124,7 @@ void cPawn::KilledBy(cPawn * a_Killer)
short OldHealth = m_Health; short OldHealth = m_Health;
m_Health = 0; m_Health = 0;
if (cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_KILLED, 2, this, a_Killer)) if (cRoot::Get()->GetPluginManager()->CallHookKilled(*this, a_Killer))
{ {
// Plugin wants to 'unkill' the pawn. Set health back and abort // Plugin wants to 'unkill' the pawn. Set health back and abort
m_Health = OldHealth; m_Health = OldHealth;

View File

@ -174,7 +174,7 @@ void cPlayer::Tick(float a_Dt, MTRand & a_TickRandom)
} }
else if (m_bDirtyPosition) else if (m_bDirtyPosition)
{ {
cRoot::Get()->GetPluginManager()->CallHook( cPluginManager::E_PLUGIN_PLAYER_MOVE, 1, this ); cRoot::Get()->GetPluginManager()->CallHookPlayerMoved(*this);
float DiffX = (float)(GetPosX() - m_LastPosX ); float DiffX = (float)(GetPosX() - m_LastPosX );
float DiffY = (float)(GetPosY() - m_LastPosY ); float DiffY = (float)(GetPosY() - m_LastPosY );
@ -1054,7 +1054,7 @@ void cPlayer::UseEquippedItem()
{ {
if (GetInventory().GetEquippedItem().DamageItem()) if (GetInventory().GetEquippedItem().DamageItem())
{ {
LOG("Player %s Broke ID: %i", GetClientHandle()->GetUsername().c_str(), GetInventory().GetEquippedItem().m_ItemID); LOG("Player %s Broke ID: %i", GetClientHandle()->GetUsername().c_str(), GetInventory().GetEquippedItem().m_ItemType);
GetInventory().RemoveItem( GetInventory().GetEquippedItem()); GetInventory().RemoveItem( GetInventory().GetEquippedItem());
} }
} }

View File

@ -65,7 +65,8 @@ public:
inline cInventory & GetInventory(void) { return m_Inventory; } // tolua_export inline cInventory & GetInventory(void) { return m_Inventory; } // tolua_export
inline const cInventory & GetInventory(void) const { return m_Inventory; } inline const cInventory & GetInventory(void) const { return m_Inventory; }
inline const cItem & GetEquippedItem(void) const {return GetInventory().GetEquippedItem(); } // tolua_export inline cItem & GetEquippedItem(void) { return GetInventory().GetEquippedItem(); } // tolua_export
inline const cItem & GetEquippedItem(void) const { return GetInventory().GetEquippedItem(); }
virtual void TeleportTo(double a_PosX, double a_PosY, double a_PosZ) override; virtual void TeleportTo(double a_PosX, double a_PosY, double a_PosZ) override;

View File

@ -3,6 +3,7 @@
#include "Plugin.h" #include "Plugin.h"
#include "Pawn.h" #include "Pawn.h"
#include "Player.h"
@ -16,16 +17,14 @@ cPlugin::cPlugin( const AString & a_PluginDirectory )
{ {
} }
cPlugin::~cPlugin() cPlugin::~cPlugin()
{ {
} }
// bool cPlugin::Initialize()
// {
// LOG("cPlugin::Initialize()");
// return false;
// }
@ -39,38 +38,8 @@ void cPlugin::Tick(float a_Dt)
bool cPlugin::OnBlockDig(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta) /*
{ // TODO
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_Status);
UNUSED(a_OldBlock);
UNUSED(a_OldMeta);
return false;
}
bool cPlugin::OnBlockPlace(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, const cItem & a_HeldItem)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_HeldItem);
return false;
}
bool cPlugin::OnBlockToPickup(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups) bool cPlugin::OnBlockToPickup(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups)
{ {
UNUSED(a_BlockType); UNUSED(a_BlockType);
@ -80,6 +49,8 @@ bool cPlugin::OnBlockToPickup(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, con
UNUSED(a_Pickups); UNUSED(a_Pickups);
return false; return false;
} }
*/
@ -96,11 +67,12 @@ bool cPlugin::OnChat(cPlayer * a_Player, const AString & a_Message)
void cPlugin::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_ChunkZ) bool cPlugin::OnChunkGenerated(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
{ {
UNUSED(a_World); UNUSED(a_World);
UNUSED(a_ChunkX); UNUSED(a_ChunkX);
UNUSED(a_ChunkZ); UNUSED(a_ChunkZ);
return false;
} }
@ -154,7 +126,7 @@ bool cPlugin::OnDisconnect(cPlayer * a_Player, const AString & a_Reason)
bool cPlugin::OnKilled(cPawn * a_Killed, cEntity * a_Killer) bool cPlugin::OnKilled(cPawn & a_Killed, cEntity * a_Killer)
{ {
UNUSED(a_Killed); UNUSED(a_Killed);
UNUSED(a_Killer); UNUSED(a_Killer);
@ -177,7 +149,39 @@ bool cPlugin::OnLogin(cClientHandle * a_Client, int a_ProtocolVersion, const ASt
bool cPlugin::OnPlayerJoin(cPlayer * a_Player) bool cPlugin::OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_BlockType);
UNUSED(a_BlockMeta);
return false;
}
bool cPlugin::OnPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_BlockType);
UNUSED(a_BlockMeta);
return false;
}
bool cPlugin::OnPlayerEating(cPlayer & a_Player)
{ {
UNUSED(a_Player); UNUSED(a_Player);
return false; return false;
@ -187,18 +191,192 @@ bool cPlugin::OnPlayerJoin(cPlayer * a_Player)
void cPlugin::OnPlayerMove(cPlayer * a_Player) bool cPlugin::OnPlayerJoined(cPlayer & a_Player)
{ {
UNUSED(a_Player); UNUSED(a_Player);
return false;
} }
void cPlugin::OnPlayerSpawn(cPlayer * a_Player) bool cPlugin::OnPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status)
{ {
UNUSED(a_Player); UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_Status);
return false;
}
bool cPlugin::OnPlayerMoved(cPlayer & a_Player)
{
UNUSED(a_Player);
return false;
}
bool cPlugin::OnPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_CursorX);
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
UNUSED(a_BlockType);
UNUSED(a_BlockMeta);
return false;
}
bool cPlugin::OnPlayerPlacingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_CursorX);
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
UNUSED(a_BlockType);
UNUSED(a_BlockMeta);
return false;
}
bool cPlugin::OnPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_CursorX);
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
return false;
}
bool cPlugin::OnPlayerShooting(cPlayer & a_Player)
{
UNUSED(a_Player);
return false;
}
bool cPlugin::OnPlayerSpawned(cPlayer & a_Player)
{
UNUSED(a_Player);
return false;
}
bool cPlugin::OnPlayerTossingItem(cPlayer & a_Player)
{
UNUSED(a_Player);
return false;
}
bool cPlugin::OnPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_CursorX);
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
UNUSED(a_BlockType);
UNUSED(a_BlockMeta);
return false;
}
bool cPlugin::OnPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_CursorX);
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
return false;
}
bool cPlugin::OnPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_CursorX);
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
UNUSED(a_BlockType);
UNUSED(a_BlockMeta);
return false;
}
bool cPlugin::OnPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
UNUSED(a_Player);
UNUSED(a_BlockX);
UNUSED(a_BlockY);
UNUSED(a_BlockZ);
UNUSED(a_BlockFace);
UNUSED(a_CursorX);
UNUSED(a_CursorY);
UNUSED(a_CursorZ);
return false;
} }

View File

@ -2,6 +2,11 @@
#pragma once #pragma once
#include "Item.h" #include "Item.h"
#include "PluginManager.h"
class cClientHandle; class cClientHandle;
class cPlayer; class cPlayer;
@ -28,50 +33,60 @@ class cCraftingRecipe;
class cPlugin class cPlugin
{ {
public: public:
// tolua_end
cPlugin( const AString & a_PluginDirectory ); cPlugin( const AString & a_PluginDirectory );
virtual ~cPlugin(); virtual ~cPlugin();
virtual void OnDisable() {} virtual void OnDisable(void) {}
virtual bool Initialize() = 0; virtual bool Initialize(void) = 0;
// Called each tick // Called each tick
virtual void Tick(float a_Dt); virtual void Tick(float a_Dt);
/** /**
* On all these functions, return true if you want to override default behavior * On all these functions, return true if you want to override default behavior and not call other plugins on that callback.
* You can also return false, so default behavior is used. * You can also return false, so default behavior is used.
**/ **/
virtual bool OnBlockDig (cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta); // TODO: virtual bool OnBlockToPickup (BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups);
virtual bool OnBlockPlace (cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, const cItem & a_HeldItem);
virtual bool OnBlockToPickup (BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups);
virtual bool OnChat (cPlayer * a_Player, const AString & a_Message); virtual bool OnChat (cPlayer * a_Player, const AString & a_Message);
virtual void OnChunkGenerated (cWorld * a_World, int a_ChunkX, int a_ChunkZ); virtual bool OnChunkGenerated (cWorld * a_World, int a_ChunkX, int a_ChunkZ);
virtual bool OnChunkGenerating (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cLuaChunk * a_pLuaChunk); virtual bool OnChunkGenerating (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cLuaChunk * a_pLuaChunk);
virtual bool OnCollectPickup (cPlayer * a_Player, cPickup * a_Pickup); virtual bool OnCollectPickup (cPlayer * a_Player, cPickup * a_Pickup);
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason); virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason);
virtual bool OnKilled (cPawn * a_Killed, cEntity* a_Killer ); virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username);
virtual bool OnKilled (cPawn & a_Killed, cEntity * a_Killer);
virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username); virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username);
virtual bool OnPlayerJoin (cPlayer* a_Player ); virtual bool OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
virtual void OnPlayerMove (cPlayer* a_Player ); virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
virtual void OnPlayerSpawn (cPlayer* a_Player ); virtual bool OnPlayerEating (cPlayer & a_Player);
virtual bool OnPlayerJoined (cPlayer & a_Player);
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
virtual bool OnPlayerMoved (cPlayer & a_Player);
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
virtual bool OnPlayerShooting (cPlayer & a_Player);
virtual bool OnPlayerSpawned (cPlayer & a_Player);
virtual bool OnPlayerTossingItem (cPlayer & a_Player);
virtual bool OnPlayerUsedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
virtual bool OnPlayerUsedItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
virtual bool OnPlayerUsingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
virtual bool OnTakeDamage (cPawn & a_Receiver, TakeDamageInfo & a_TakeDamageInfo); virtual bool OnTakeDamage (cPawn & a_Receiver, TakeDamageInfo & a_TakeDamageInfo);
virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player); virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player);
virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player); virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
virtual bool OnWeatherChanged (cWorld * a_World); virtual bool OnWeatherChanged (cWorld * a_World);
virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username);
// Accessors /** Called from cPluginManager::AddHook() to check if the hook can be added.
const AString & GetName() const { return m_Name; } Plugin API providers may check if the plugin is written correctly (has the hook handler function)
virtual void SetName( const AString & a_Name ) { m_Name = a_Name; } Returns true if the hook can be added (handler exists)
Descendants should also log the specific error message as a warning if they return false.
int GetVersion() const { return m_Version; } */
void SetVersion( int a_Version ) { m_Version = a_Version; } virtual bool CanAddHook(cPluginManager::PluginHook a_Hook) { return false; }
const AString & GetDirectory(void) const {return m_Directory; }
AString GetLocalDirectory(void) const; //tolua_export
struct CommandStruct struct CommandStruct
{ {
@ -80,6 +95,16 @@ public:
AString Permission; AString Permission;
}; };
// tolua_begin
const AString & GetName(void) const { return m_Name; }
void SetName(const AString & a_Name) { m_Name = a_Name; }
int GetVersion(void) const { return m_Version; }
void SetVersion(int a_Version) { m_Version = a_Version; }
const AString & GetDirectory(void) const {return m_Directory; }
AString GetLocalDirectory(void) const;
void AddCommand(const AString & a_Command, const AString & a_Description, const AString & a_Permission); void AddCommand(const AString & a_Command, const AString & a_Description, const AString & a_Permission);
// tolua_end // tolua_end

View File

@ -199,7 +199,7 @@ void cPluginManager::Tick(float a_Dt)
ReloadPluginsNow(); ReloadPluginsNow();
} }
HookMap::iterator Plugins = m_Hooks.find( E_PLUGIN_TICK ); HookMap::iterator Plugins = m_Hooks.find(HOOK_TICK);
if( Plugins != m_Hooks.end() ) if( Plugins != m_Hooks.end() )
{ {
for( PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr ) for( PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr )
@ -213,133 +213,33 @@ void cPluginManager::Tick(float a_Dt)
bool cPluginManager::CallHook(PluginHook a_Hook, unsigned int a_NumArgs, ...) /*
bool cPluginManager::CallHookBlockToPickup(
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups
)
{ {
HookMap::iterator Plugins = m_Hooks.find( a_Hook ); HookMap::iterator Plugins = m_Hooks.find(HOOK_POST_CRAFTING);
if (Plugins == m_Hooks.end())
{
return false;
}
switch( a_Hook )
{
case HOOK_PLAYER_JOIN:
{
if( a_NumArgs != 1 ) break;
va_list argptr;
va_start( argptr, a_NumArgs);
cPlayer* Player = va_arg(argptr, cPlayer* );
va_end (argptr);
for( PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr )
{
if( (*itr)->OnPlayerJoin( Player ) )
return true;
}
break;
}
case HOOK_PLAYER_MOVE:
{
if( a_NumArgs != 1 ) break;
va_list argptr;
va_start( argptr, a_NumArgs);
cPlayer* Player = va_arg(argptr, cPlayer* );
va_end (argptr);
for( PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr )
{
(*itr)->OnPlayerMove( Player );
}
break;
}
case HOOK_KILLED:
{
if( a_NumArgs != 2 ) break;
va_list argptr;
va_start( argptr, a_NumArgs);
cPawn* Killed = va_arg(argptr, cPawn* );
cEntity* Killer = va_arg(argptr, cEntity* );
va_end (argptr);
for( PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr )
{
if( (*itr)->OnKilled( Killed, Killer ) )
return true;
}
break;
}
case HOOK_CHUNK_GENERATED:
{
if (a_NumArgs != 3)
{
break;
}
va_list argptr;
va_start( argptr, a_NumArgs);
cWorld * World = va_arg(argptr, cWorld *);
int ChunkX = va_arg(argptr, int);
int ChunkZ = va_arg(argptr, int);
va_end (argptr);
for( PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr )
{
(*itr)->OnChunkGenerated(World, ChunkX, ChunkZ);
}
break;
}
case HOOK_PLAYER_SPAWN:
{
if (a_NumArgs != 1)
{
break;
}
va_list argptr;
va_start( argptr, a_NumArgs);
cPlayer * Player = va_arg(argptr, cPlayer *);
va_end (argptr);
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
(*itr)->OnPlayerSpawn(Player);
}
break;
}
default:
{
LOGWARNING("cPluginManager: Calling Unknown hook: %i", a_Hook );
ASSERT(!"Calling an unknown hook");
break;
}
} // switch (a_Hook)
return false;
}
bool cPluginManager::CallHookLogin(cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_LOGIN);
if (Plugins == m_Hooks.end()) if (Plugins == m_Hooks.end())
{ {
return false; return false;
} }
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr) for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{ {
if ((*itr)->OnLogin(a_Client, a_ProtocolVersion, a_Username)) if ((*itr)->OnBlockToPickup(a_BlockType, a_BlockMeta, a_Player, a_EquippedItem, a_Pickups))
{ {
return true; return true;
} }
} }
return false; return false;
} }
*/
/*
bool cPluginManager::CallHookBlockDig(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta) bool cPluginManager::CallHookBlockDig(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta)
{ {
HookMap::iterator Plugins = m_Hooks.find(HOOK_BLOCK_DIG); HookMap::iterator Plugins = m_Hooks.find(HOOK_BLOCK_DIG);
@ -356,11 +256,13 @@ bool cPluginManager::CallHookBlockDig(cPlayer * a_Player, int a_BlockX, int a_Bl
} }
return false; return false;
} }
*/
/*
bool cPluginManager::CallHookBlockPlace(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, const cItem & a_HeldItem) bool cPluginManager::CallHookBlockPlace(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, const cItem & a_HeldItem)
{ {
HookMap::iterator Plugins = m_Hooks.find(HOOK_BLOCK_PLACE); HookMap::iterator Plugins = m_Hooks.find(HOOK_BLOCK_PLACE);
@ -377,6 +279,7 @@ bool cPluginManager::CallHookBlockPlace(cPlayer * a_Player, int a_BlockX, int a_
} }
return false; return false;
} }
*/
@ -425,6 +328,27 @@ bool cPluginManager::CallHookChat(cPlayer * a_Player, const AString & a_Message)
bool cPluginManager::CallHookChunkGenerated(cWorld * a_World, int a_ChunkX, int a_ChunkZ)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_CHUNK_GENERATED);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnChunkGenerated(a_World, a_ChunkX, a_ChunkZ))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cLuaChunk * a_LuaChunk) bool cPluginManager::CallHookChunkGenerating(cWorld * a_World, int a_ChunkX, int a_ChunkZ, cLuaChunk * a_LuaChunk)
{ {
HookMap::iterator Plugins = m_Hooks.find(HOOK_CHUNK_GENERATING); HookMap::iterator Plugins = m_Hooks.find(HOOK_CHUNK_GENERATING);
@ -509,6 +433,405 @@ bool cPluginManager::CallHookDisconnect(cPlayer * a_Player, const AString & a_Re
bool cPluginManager::CallHookHandshake(cClientHandle * a_ClientHandle, const AString & a_Username)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_HANDSHAKE);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnHandshake(a_ClientHandle, a_Username))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookKilled(cPawn & a_Victim, cEntity * a_Killer)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_KILLED);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnKilled(a_Victim, a_Killer))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookLogin(cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_LOGIN);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnLogin(a_Client, a_ProtocolVersion, a_Username))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_BREAKING_BLOCK);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerBreakingBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerBrokenBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_BROKEN_BLOCK);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerBrokenBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_BlockType, a_BlockMeta))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerEating(cPlayer & a_Player)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_EATING);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerEating(a_Player))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerJoined(cPlayer & a_Player)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_JOINED);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerJoined(a_Player))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerLeftClick(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_LEFT_CLICK);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerLeftClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_Status))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerMoved(cPlayer & a_Player)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_MOVED);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerMoved(a_Player))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerPlacedBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_PLACED_BLOCK);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerPlacedBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerPlacingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_PLACING_BLOCK);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerPlacingBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerRightClick(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_RIGHTCLICK);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerRightClick(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerShooting(cPlayer & a_Player)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_SHOOTING);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerShooting(a_Player))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerSpawned(cPlayer & a_Player)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_SPAWNED);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerSpawned(a_Player))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerTossingItem(cPlayer & a_Player)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_TOSSING_ITEM);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerTossingItem(a_Player))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerUsedBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_USED_BLOCK);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerUsedBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerUsedItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_USED_ITEM);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerUsedItem(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerUsingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_USING_BLOCK);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerUsingBlock(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, a_BlockType, a_BlockMeta))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPlayerUsingItem(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_PLAYER_USING_ITEM);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnPlayerUsingItem(a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookPostCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) bool cPluginManager::CallHookPostCrafting(const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe)
{ {
HookMap::iterator Plugins = m_Hooks.find(HOOK_POST_CRAFTING); HookMap::iterator Plugins = m_Hooks.find(HOOK_POST_CRAFTING);
@ -572,51 +895,6 @@ bool cPluginManager::CallHookTakeDamage(cPawn & a_Receiver, TakeDamageInfo & a_T
bool cPluginManager::CallHookBlockToPickup(
BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta,
const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups
)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_POST_CRAFTING);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnBlockToPickup(a_BlockType, a_BlockMeta, a_Player, a_EquippedItem, a_Pickups))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookWeatherChanged(cWorld * a_World)
{
HookMap::iterator Plugins = m_Hooks.find(HOOK_WEATHER_CHANGED);
if (Plugins == m_Hooks.end())
{
return false;
}
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{
if ((*itr)->OnWeatherChanged(a_World))
{
return true;
}
}
return false;
}
bool cPluginManager::CallHookUpdatingSign(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) bool cPluginManager::CallHookUpdatingSign(cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player)
{ {
HookMap::iterator Plugins = m_Hooks.find(HOOK_UPDATING_SIGN); HookMap::iterator Plugins = m_Hooks.find(HOOK_UPDATING_SIGN);
@ -659,16 +937,16 @@ bool cPluginManager::CallHookUpdatedSign(cWorld * a_World, int a_BlockX, int a_B
bool cPluginManager::CallHookHandshake(cClientHandle * a_ClientHandle, const AString & a_Username) bool cPluginManager::CallHookWeatherChanged(cWorld * a_World)
{ {
HookMap::iterator Plugins = m_Hooks.find(HOOK_HANDSHAKE); HookMap::iterator Plugins = m_Hooks.find(HOOK_WEATHER_CHANGED);
if (Plugins == m_Hooks.end()) if (Plugins == m_Hooks.end())
{ {
return false; return false;
} }
for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr) for (PluginList::iterator itr = Plugins->second.begin(); itr != Plugins->second.end(); ++itr)
{ {
if ((*itr)->OnHandshake(a_ClientHandle, a_Username)) if ((*itr)->OnWeatherChanged(a_World))
{ {
return true; return true;
} }
@ -758,22 +1036,10 @@ bool cPluginManager::LoadPlugin( AString & a_PluginName )
void cPluginManager::RemoveHooks(cPlugin * a_Plugin) void cPluginManager::RemoveHooks(cPlugin * a_Plugin)
{ {
m_Hooks[ E_PLUGIN_TICK].remove ( a_Plugin ); for (HookMap::iterator itr = m_Hooks.begin(), end = m_Hooks.end(); itr != end; ++itr)
m_Hooks[ E_PLUGIN_CHAT].remove ( a_Plugin ); {
m_Hooks[ E_PLUGIN_COLLECT_ITEM].remove ( a_Plugin ); itr->second.remove(a_Plugin);
m_Hooks[ E_PLUGIN_BLOCK_DIG].remove ( a_Plugin ); }
m_Hooks[ E_PLUGIN_BLOCK_PLACE].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_DISCONNECT].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_HANDSHAKE].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_LOGIN].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_PLAYER_SPAWN].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_PLAYER_JOIN].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_PLAYER_MOVE].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_TAKE_DAMAGE].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_KILLED].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_CHUNK_GENERATED ].remove ( a_Plugin );
m_Hooks[ E_PLUGIN_CHUNK_GENERATING ].remove( a_Plugin );
m_Hooks[ E_PLUGIN_BLOCK_TO_DROPS ].remove ( a_Plugin );
} }
@ -832,7 +1098,11 @@ void cPluginManager::AddHook( cPlugin* a_Plugin, PluginHook a_Hook )
{ {
if (!a_Plugin) if (!a_Plugin)
{ {
LOGWARN("Called cPluginManager::AddHook while a_Plugin is NULL"); LOGWARN("Called cPluginManager::AddHook() with a_Plugin == NULL");
return;
}
if (!a_Plugin->CanAddHook(a_Hook))
{
return; return;
} }
PluginList & Plugins = m_Hooks[a_Hook]; PluginList & Plugins = m_Hooks[a_Hook];
@ -862,3 +1132,7 @@ bool cPluginManager::HasPlugin( cPlugin* a_Plugin ) const
} }
return false; return false;
} }

View File

@ -46,48 +46,40 @@ public: //tolua_export
// tolua_begin // tolua_begin
enum PluginHook enum PluginHook
{ {
HOOK_TICK,
HOOK_CHAT, HOOK_CHAT,
HOOK_COLLECT_PICKUP,
HOOK_COLLECT_ITEM = HOOK_COLLECT_PICKUP, // OBSOLETE, use HOOK_COLLECT_PICKUP instead
HOOK_BLOCK_DIG,
HOOK_BLOCK_PLACE,
HOOK_DISCONNECT,
HOOK_HANDSHAKE,
HOOK_LOGIN,
HOOK_PLAYER_SPAWN,
HOOK_PLAYER_JOIN,
HOOK_PLAYER_MOVE,
HOOK_TAKE_DAMAGE, // cPawn, TakeDamageInfo
HOOK_KILLED,
HOOK_CHUNK_GENERATED, HOOK_CHUNK_GENERATED,
HOOK_CHUNK_GENERATING, HOOK_CHUNK_GENERATING,
HOOK_BLOCK_TO_DROPS, HOOK_COLLECT_PICKUP,
HOOK_PRE_CRAFTING, /// cPlayer, cCraftingGrid, cCraftingRecipe HOOK_CRAFTING_NO_RECIPE,
HOOK_CRAFTING_NO_RECIPE, /// cPlayer, cCraftingGrid, cCraftingRecipe HOOK_DISCONNECT,
HOOK_POST_CRAFTING, /// cPlayer, cCraftingGrid, cCraftingRecipe HOOK_HANDSHAKE,
HOOK_BLOCK_TO_PICKUP, /// BlockType, BlockMeta, cPlayer, cItem, cItems HOOK_KILLED,
HOOK_WEATHER_CHANGED, /// cWorld HOOK_LOGIN,
HOOK_UPDATING_SIGN, /// cWorld, int, int, int, string, string, string, string HOOK_PLAYER_BREAKING_BLOCK,
HOOK_UPDATED_SIGN, /// cWorld, int, int, int, string, string, string, string HOOK_PLAYER_BROKEN_BLOCK,
HOOK_PLAYER_EATING,
HOOK_PLAYER_JOINED,
HOOK_PLAYER_LEFT_CLICK,
HOOK_PLAYER_MOVED,
HOOK_PLAYER_PLACED_BLOCK,
HOOK_PLAYER_PLACING_BLOCK,
HOOK_PLAYER_RIGHTCLICK,
HOOK_PLAYER_SHOOTING,
HOOK_PLAYER_SPAWNED,
HOOK_PLAYER_TOSSING_ITEM,
HOOK_PLAYER_USED_BLOCK,
HOOK_PLAYER_USED_ITEM,
HOOK_PLAYER_USING_BLOCK,
HOOK_PLAYER_USING_ITEM,
HOOK_POST_CRAFTING,
HOOK_PRE_CRAFTING,
HOOK_TAKE_DAMAGE,
HOOK_TICK,
HOOK_UPDATED_SIGN,
HOOK_UPDATING_SIGN,
HOOK_WEATHER_CHANGED,
// E_PLUGIN_ names are obsolete, but are kept for compatibility reasons // Note that if a hook type is added, it may need processing in cPlugin::CanAddHook() descendants!
E_PLUGIN_TICK = HOOK_TICK,
E_PLUGIN_CHAT = HOOK_CHAT,
E_PLUGIN_COLLECT_ITEM = HOOK_COLLECT_ITEM,
E_PLUGIN_BLOCK_DIG = HOOK_BLOCK_DIG,
E_PLUGIN_BLOCK_PLACE = HOOK_BLOCK_PLACE,
E_PLUGIN_DISCONNECT = HOOK_DISCONNECT,
E_PLUGIN_HANDSHAKE = HOOK_HANDSHAKE,
E_PLUGIN_LOGIN = HOOK_LOGIN,
E_PLUGIN_PLAYER_SPAWN = HOOK_PLAYER_SPAWN,
E_PLUGIN_PLAYER_JOIN = HOOK_PLAYER_JOIN,
E_PLUGIN_PLAYER_MOVE = HOOK_PLAYER_MOVE,
E_PLUGIN_TAKE_DAMAGE = HOOK_TAKE_DAMAGE,
E_PLUGIN_KILLED = HOOK_KILLED,
E_PLUGIN_CHUNK_GENERATED = HOOK_CHUNK_GENERATED,
E_PLUGIN_CHUNK_GENERATING = HOOK_CHUNK_GENERATING,
E_PLUGIN_BLOCK_TO_DROPS = HOOK_BLOCK_TO_DROPS,
} ; } ;
// tolua_end // tolua_end
@ -105,25 +97,38 @@ public: //tolua_export
unsigned int GetNumPlugins() const; // tolua_export unsigned int GetNumPlugins() const; // tolua_export
// If the hook returns true, no further hook is called and the functions return false // TODO: bool CallHookBlockToPickup (BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups);
bool CallHook( PluginHook a_Hook, unsigned int a_NumArgs, ... );
bool CallHookBlockDig (cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status, BLOCKTYPE OldBlock, NIBBLETYPE OldMeta);
bool CallHookBlockPlace (cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, const cItem & a_HeldItem);
bool CallHookBlockToPickup (BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups);
bool CallHookChat (cPlayer * a_Player, const AString & a_Message); bool CallHookChat (cPlayer * a_Player, const AString & a_Message);
bool CallHookChunkGenerated (cWorld * a_World, int a_ChunkX, int a_ChunkZ);
bool CallHookChunkGenerating (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cLuaChunk * a_Chunk); bool CallHookChunkGenerating (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cLuaChunk * a_Chunk);
bool CallHookCollectPickup (cPlayer * a_Player, cPickup & a_Pickup); bool CallHookCollectPickup (cPlayer * a_Player, cPickup & a_Pickup);
bool CallHookCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); bool CallHookCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookDisconnect (cPlayer * a_Player, const AString & a_Reason); bool CallHookDisconnect (cPlayer * a_Player, const AString & a_Reason);
bool CallHookHandshake (cClientHandle * a_ClientHandle, const AString & a_Username);
bool CallHookKilled (cPawn & a_Victim, cEntity * a_Killer);
bool CallHookLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username); bool CallHookLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username);
bool CallHookPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerEating (cPlayer & a_Player);
bool CallHookPlayerJoined (cPlayer & a_Player);
bool CallHookPlayerMoved (cPlayer & a_Player);
bool CallHookPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status);
bool CallHookPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
bool CallHookPlayerShooting (cPlayer & a_Player);
bool CallHookPlayerSpawned (cPlayer & a_Player);
bool CallHookPlayerTossingItem (cPlayer & a_Player);
bool CallHookPlayerUsedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerUsedItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
bool CallHookPlayerUsingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);
bool CallHookPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ);
bool CallHookPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); bool CallHookPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe); bool CallHookPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe);
bool CallHookTakeDamage (cPawn & a_Receiver, TakeDamageInfo & a_TDI); bool CallHookTakeDamage (cPawn & a_Receiver, TakeDamageInfo & a_TDI);
bool CallHookUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player); bool CallHookUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player);
bool CallHookUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player); bool CallHookUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player);
bool CallHookWeatherChanged (cWorld * a_World); bool CallHookWeatherChanged (cWorld * a_World);
bool CallHookHandshake (cClientHandle * a_ClientHandle, const AString & a_Username);
bool DisablePlugin( AString & a_PluginName ); // tolua_export bool DisablePlugin( AString & a_PluginName ); // tolua_export
bool LoadPlugin( AString & a_PluginName ); // tolua_export bool LoadPlugin( AString & a_PluginName ); // tolua_export

File diff suppressed because it is too large Load Diff

View File

@ -25,37 +25,48 @@ public:
cPlugin_NewLua( const AString & a_PluginDirectory ); cPlugin_NewLua( const AString & a_PluginDirectory );
~cPlugin_NewLua(); ~cPlugin_NewLua();
virtual void OnDisable(); //tolua_export virtual void OnDisable(void) override;
virtual bool Initialize(); //tolua_export virtual bool Initialize(void) override;
virtual void Tick(float a_Dt); //tolua_export virtual void Tick(float a_Dt) override;
virtual bool OnBlockDig (cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status, BLOCKTYPE a_OldBlock, NIBBLETYPE a_OldMeta) override; // TODO: virtual bool OnBlockToPickup (BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups) override;
virtual bool OnBlockPlace (cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, const cItem & a_HeldItem) override;
virtual bool OnBlockToPickup (BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, const cPlayer * a_Player, const cItem & a_EquippedItem, cItems & a_Pickups);
virtual bool OnChat (cPlayer * a_Player, const AString & a_Message) override; virtual bool OnChat (cPlayer * a_Player, const AString & a_Message) override;
virtual void OnChunkGenerated (cWorld * a_World, int a_ChunkX, int a_ChunkZ) override; virtual bool OnChunkGenerated (cWorld * a_World, int a_ChunkX, int a_ChunkZ) override;
virtual bool OnChunkGenerating (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cLuaChunk * a_pLuaChunk ) override; virtual bool OnChunkGenerating (cWorld * a_World, int a_ChunkX, int a_ChunkZ, cLuaChunk * a_pLuaChunk ) override;
virtual bool OnCollectPickup (cPlayer * a_Player, cPickup * a_Pickup) override; virtual bool OnCollectPickup (cPlayer * a_Player, cPickup * a_Pickup) override;
virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; virtual bool OnCraftingNoRecipe (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason) override; virtual bool OnDisconnect (cPlayer * a_Player, const AString & a_Reason) override;
virtual bool OnKilled (cPawn * a_Killed, cEntity* a_Killer ) override; virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username) override;
virtual bool OnKilled (cPawn & a_Killed, cEntity * a_Killer) override;
virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) override; virtual bool OnLogin (cClientHandle * a_Client, int a_ProtocolVersion, const AString & a_Username) override;
virtual bool OnPlayerJoin (cPlayer * a_Player ) override; virtual bool OnPlayerBreakingBlock(cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual void OnPlayerMove (cPlayer * a_Player ) override; virtual bool OnPlayerBrokenBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual void OnPlayerSpawn (cPlayer * a_Player ) override; virtual bool OnPlayerEating (cPlayer & a_Player) override;
virtual bool OnPlayerJoined (cPlayer & a_Player) override;
virtual bool OnPlayerMoved (cPlayer & a_Player) override;
virtual bool OnPlayerLeftClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, char a_Status) override;
virtual bool OnPlayerPlacedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerPlacingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerRightClick (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual bool OnPlayerShooting (cPlayer & a_Player) override;
virtual bool OnPlayerSpawned (cPlayer & a_Player) override;
virtual bool OnPlayerTossingItem (cPlayer & a_Player) override;
virtual bool OnPlayerUsedBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerUsedItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual bool OnPlayerUsingBlock (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override;
virtual bool OnPlayerUsingItem (cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; virtual bool OnPostCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override; virtual bool OnPreCrafting (const cPlayer * a_Player, const cCraftingGrid * a_Grid, cCraftingRecipe * a_Recipe) override;
virtual bool OnTakeDamage (cPawn & a_Receiver, TakeDamageInfo & a_TakeDamageInfo) override; virtual bool OnTakeDamage (cPawn & a_Receiver, TakeDamageInfo & a_TakeDamageInfo) override;
virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) override; virtual bool OnUpdatedSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, const AString & a_Line1, const AString & a_Line2, const AString & a_Line3, const AString & a_Line4, cPlayer * a_Player) override;
virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override; virtual bool OnUpdatingSign (cWorld * a_World, int a_BlockX, int a_BlockY, int a_BlockZ, AString & a_Line1, AString & a_Line2, AString & a_Line3, AString & a_Line4, cPlayer * a_Player) override;
virtual bool OnWeatherChanged (cWorld * a_World) override; virtual bool OnWeatherChanged (cWorld * a_World) override;
virtual bool OnHandshake (cClientHandle * a_Client, const AString & a_Username) override;
virtual void SetName( const AString & a_Name ) override { cPlugin::SetName(a_Name); } virtual bool CanAddHook(cPluginManager::PluginHook a_Hook) override;
// cWebPlugin override // cWebPlugin override
virtual const AString & GetName(void) const {return cPlugin::GetName(); } virtual const AString & GetWebTitle(void) const {return GetName(); }
// cWebPlugin and WebAdmin stuff // cWebPlugin and WebAdmin stuff
virtual AString HandleWebRequest( HTTPRequest * a_Request ) override; virtual AString HandleWebRequest( HTTPRequest * a_Request ) override;
@ -65,11 +76,18 @@ public:
cCriticalSection & GetCriticalSection() { return m_CriticalSection; } cCriticalSection & GetCriticalSection() { return m_CriticalSection; }
private: protected:
bool PushFunction(const char * a_FunctionName, bool a_bLogError = true); bool PushFunction(const char * a_FunctionName, bool a_bLogError = true);
bool CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName ); // a_FunctionName is only used for error messages, nothing else bool CallFunction(int a_NumArgs, int a_NumResults, const char * a_FunctionName ); // a_FunctionName is only used for error messages, nothing else
/// Returns the name of Lua function that should handle the specified hook
const char * GetHookFnName(cPluginManager::PluginHook a_Hook);
cCriticalSection m_CriticalSection; cCriticalSection m_CriticalSection;
lua_State * m_LuaState; lua_State * m_LuaState;
} ; // tolua_export } ; // tolua_export

View File

@ -978,8 +978,8 @@ int cProtocol125::ParseBlockDig(void)
HANDLE_PACKET_READ(ReadBEInt, int, PosX); HANDLE_PACKET_READ(ReadBEInt, int, PosX);
HANDLE_PACKET_READ(ReadByte, Byte, PosY); HANDLE_PACKET_READ(ReadByte, Byte, PosY);
HANDLE_PACKET_READ(ReadBEInt, int, PosZ); HANDLE_PACKET_READ(ReadBEInt, int, PosZ);
HANDLE_PACKET_READ(ReadChar, char, Direction); HANDLE_PACKET_READ(ReadChar, char, BlockFace);
m_Client->HandleBlockDig(PosX, PosY, PosZ, Direction, Status); m_Client->HandleLeftClick(PosX, PosY, PosZ, BlockFace, Status);
return PARSE_OK; return PARSE_OK;
} }
@ -992,7 +992,7 @@ int cProtocol125::ParseBlockPlace(void)
HANDLE_PACKET_READ(ReadBEInt, int, PosX); HANDLE_PACKET_READ(ReadBEInt, int, PosX);
HANDLE_PACKET_READ(ReadByte, Byte, PosY); HANDLE_PACKET_READ(ReadByte, Byte, PosY);
HANDLE_PACKET_READ(ReadBEInt, int, PosZ); HANDLE_PACKET_READ(ReadBEInt, int, PosZ);
HANDLE_PACKET_READ(ReadChar, char, Direction); HANDLE_PACKET_READ(ReadChar, char, BlockFace);
cItem HeldItem; cItem HeldItem;
int res = ParseItem(HeldItem); int res = ParseItem(HeldItem);
@ -1001,7 +1001,8 @@ int cProtocol125::ParseBlockPlace(void)
return res; return res;
} }
m_Client->HandleBlockPlace(PosX, PosY, PosZ, Direction, HeldItem); // 1.2.5 didn't have any cursor position, so use 8, 8, 8, so that halfslabs and stairs work correctly and the special value is recognizable.
m_Client->HandleRightClick(PosX, PosY, PosZ, BlockFace, 8, 8, 8, HeldItem);
return PARSE_OK; return PARSE_OK;
} }

View File

@ -484,7 +484,7 @@ int cProtocol132::ParseBlockPlace(void)
HANDLE_PACKET_READ(ReadBEInt, int, PosX); HANDLE_PACKET_READ(ReadBEInt, int, PosX);
HANDLE_PACKET_READ(ReadByte, Byte, PosY); HANDLE_PACKET_READ(ReadByte, Byte, PosY);
HANDLE_PACKET_READ(ReadBEInt, int, PosZ); HANDLE_PACKET_READ(ReadBEInt, int, PosZ);
HANDLE_PACKET_READ(ReadChar, char, Direction); HANDLE_PACKET_READ(ReadChar, char, BlockFace);
cItem HeldItem; cItem HeldItem;
int res = ParseItem(HeldItem); int res = ParseItem(HeldItem);
@ -497,7 +497,7 @@ int cProtocol132::ParseBlockPlace(void)
HANDLE_PACKET_READ(ReadChar, char, CursorY); HANDLE_PACKET_READ(ReadChar, char, CursorY);
HANDLE_PACKET_READ(ReadChar, char, CursorZ); HANDLE_PACKET_READ(ReadChar, char, CursorZ);
m_Client->HandleBlockPlace(PosX, PosY, PosZ, Direction, HeldItem); m_Client->HandleRightClick(PosX, PosY, PosZ, BlockFace, CursorX, CursorY, CursorZ, HeldItem);
return PARSE_OK; return PARSE_OK;
} }

View File

@ -80,16 +80,6 @@ struct cServer::sServerState
cServer * cServer::GetServer()
{
LOGWARN("WARNING: Using deprecated function cServer::GetServer() use cRoot::Get()->GetServer() instead!");
return cRoot::Get()->GetServer();
}
void cServer::ServerListenThread( void *a_Args ) void cServer::ServerListenThread( void *a_Args )
{ {
LOG("ServerListenThread"); LOG("ServerListenThread");
@ -173,7 +163,8 @@ bool cServer::InitServer(cIniFile & a_SettingsIni)
printf("email: faketruth@gmail.com\n\n"); printf("email: faketruth@gmail.com\n\n");
LOG("Starting up server."); LOG("Starting up server.");
LOGINFO("Compatible clients: %s, protocol versions %s", MCS_CLIENT_VERSIONS, MCS_PROTOCOL_VERSIONS); LOGINFO("Compatible clients: %s", MCS_CLIENT_VERSIONS);
LOGINFO("Compatible protocol versions %s", MCS_PROTOCOL_VERSIONS);
if (cSocket::WSAStartup() != 0) // Only does anything on Windows, but whatever if (cSocket::WSAStartup() != 0) // Only does anything on Windows, but whatever
{ {

View File

@ -32,8 +32,6 @@ typedef std::list<cClientHandle *> cClientHandleList;
class cServer // tolua_export class cServer // tolua_export
{ // tolua_export { // tolua_export
public: // tolua_export public: // tolua_export
static cServer * GetServer(); //tolua_export
bool InitServer(cIniFile & a_SettingsIni); bool InitServer(cIniFile & a_SettingsIni);
int GetPort() { return m_iServerPort; } int GetPort() { return m_iServerPort; }

View File

@ -1,38 +1,41 @@
#pragma once #pragma once
class cStairs // tolua_export class cStairs // tolua_export
{ // tolua_export { // tolua_export
public: public:
static NIBBLETYPE RotationToMetaData( float a_Rotation, char a_BlockFace) //tolua_export /// Converts player rotation to stair rotation metadata. To get upside-down stairs, OR with 0x4
static NIBBLETYPE RotationToMetaData(float a_Rotation) // tolua_export
{ // tolua_export { // tolua_export
a_Rotation += 90 + 45; // So its not aligned with axis a_Rotation += 90 + 45; // So its not aligned with axis
NIBBLETYPE result = 0x0; NIBBLETYPE result = 0x0;
if (a_BlockFace == BLOCK_FACE_BOTTOM)
{
result = 0x4;
}
if (a_Rotation > 360.f) if (a_Rotation > 360.f)
{ {
a_Rotation -= 360.f; a_Rotation -= 360.f;
} }
if ((a_Rotation >= 0.f) && (a_Rotation < 90.f)) if ((a_Rotation >= 0.f) && (a_Rotation < 90.f))
{ {
return result; return 0x0;
} }
else if ((a_Rotation >= 180) && (a_Rotation < 270)) else if ((a_Rotation >= 180) && (a_Rotation < 270))
{ {
result += 0x1; return 0x1;
} }
else if ((a_Rotation >= 90) && (a_Rotation < 180)) else if ((a_Rotation >= 90) && (a_Rotation < 180))
{ {
result += 0x2; return 0x2;
} }
else else
{ {
result += 0x3; return 0x3;
} }
return result;
} // tolua_export } // tolua_export
} ; // tolua_export } ; // tolua_export

View File

@ -15,7 +15,7 @@ public:
{ // tolua_export { // tolua_export
switch (a_Direction) switch (a_Direction)
{ {
case BLOCK_FACE_BOTTOM: ASSERT(!"Shouldn't be getting this direction"); return 0; case BLOCK_FACE_BOTTOM: ASSERT(!"Shouldn't be getting this face"); return 0;
case BLOCK_FACE_TOP: return E_META_TORCH_FLOOR; case BLOCK_FACE_TOP: return E_META_TORCH_FLOOR;
case BLOCK_FACE_EAST: return E_META_TORCH_EAST; case BLOCK_FACE_EAST: return E_META_TORCH_EAST;
case BLOCK_FACE_WEST: return E_META_TORCH_WEST; case BLOCK_FACE_WEST: return E_META_TORCH_WEST;

View File

@ -73,27 +73,27 @@ void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, bool a_IsRightClick,
if (a_IsRightClick) if (a_IsRightClick)
{ {
// Right clicked // Right clicked
if (DraggingItem.m_ItemID <= 0) // Empty-handed? if (DraggingItem.m_ItemType <= 0) // Empty-handed?
{ {
DraggingItem.m_ItemCount = (char)(((float)Slot.m_ItemCount) / 2.f + 0.5f); DraggingItem.m_ItemCount = (char)(((float)Slot.m_ItemCount) / 2.f + 0.5f);
Slot.m_ItemCount -= DraggingItem.m_ItemCount; Slot.m_ItemCount -= DraggingItem.m_ItemCount;
DraggingItem.m_ItemID = Slot.m_ItemID; DraggingItem.m_ItemType = Slot.m_ItemType;
DraggingItem.m_ItemHealth = Slot.m_ItemHealth; DraggingItem.m_ItemDamage = Slot.m_ItemDamage;
if (Slot.m_ItemCount <= 0) if (Slot.m_ItemCount <= 0)
{ {
Slot.Empty(); Slot.Empty();
} }
} }
else if ((Slot.m_ItemID <= 0) || DraggingItem.IsEqual(Slot)) else if ((Slot.m_ItemType <= 0) || DraggingItem.IsEqual(Slot))
{ {
// Drop one item in slot // Drop one item in slot
cItemHandler * Handler = ItemHandler(Slot.m_ItemID); cItemHandler * Handler = ItemHandler(Slot.m_ItemType);
if ((DraggingItem.m_ItemCount > 0) && (Slot.m_ItemCount < Handler->GetMaxStackSize())) if ((DraggingItem.m_ItemCount > 0) && (Slot.m_ItemCount < Handler->GetMaxStackSize()))
{ {
Slot.m_ItemID = DraggingItem.m_ItemID; Slot.m_ItemType = DraggingItem.m_ItemType;
Slot.m_ItemCount++; Slot.m_ItemCount++;
Slot.m_ItemHealth = DraggingItem.m_ItemHealth; Slot.m_ItemDamage = DraggingItem.m_ItemDamage;
DraggingItem.m_ItemCount--; DraggingItem.m_ItemCount--;
} }
if (DraggingItem.m_ItemCount <= 0) if (DraggingItem.m_ItemCount <= 0)
@ -122,7 +122,7 @@ void cSlotArea::Clicked(cPlayer & a_Player, int a_SlotNum, bool a_IsRightClick,
else else
{ {
// Same type, add items: // Same type, add items:
cItemHandler * Handler = ItemHandler(DraggingItem.m_ItemID); cItemHandler * Handler = ItemHandler(DraggingItem.m_ItemType);
int FreeSlots = Handler->GetMaxStackSize() - Slot.m_ItemCount; int FreeSlots = Handler->GetMaxStackSize() - Slot.m_ItemCount;
if (FreeSlots < 0) if (FreeSlots < 0)
{ {
@ -366,7 +366,7 @@ void cSlotAreaCrafting::ClickedResult(cPlayer & a_Player)
} }
else if (DraggingItem.IsEqual(Recipe.GetResult())) else if (DraggingItem.IsEqual(Recipe.GetResult()))
{ {
cItemHandler * Handler = ItemHandler(Recipe.GetResult().m_ItemID); cItemHandler * Handler = ItemHandler(Recipe.GetResult().m_ItemType);
if (DraggingItem.m_ItemCount + Recipe.GetResult().m_ItemCount <= Handler->GetMaxStackSize()) if (DraggingItem.m_ItemCount + Recipe.GetResult().m_ItemCount <= Handler->GetMaxStackSize())
{ {
DraggingItem.m_ItemCount += Recipe.GetResult().m_ItemCount; DraggingItem.m_ItemCount += Recipe.GetResult().m_ItemCount;
@ -535,7 +535,7 @@ void cSlotAreaFurnace::Clicked(cPlayer & a_Player, int a_SlotNum, bool a_IsRight
return; return;
} }
if (Fuel.m_ItemID != GetSlot(0, a_Player)->m_ItemID) if (Fuel.m_ItemType != GetSlot(0, a_Player)->m_ItemType)
{ {
m_Furnace->ResetCookTimer(); m_Furnace->ResetCookTimer();
} }

View File

@ -163,7 +163,7 @@ void cWebAdmin::Request_Handler(webserver::http_request* r)
std::list< std::pair<std::string, std::string> > NameList = WebPlugin->GetTabNames(); std::list< std::pair<std::string, std::string> > NameList = WebPlugin->GetTabNames();
for( std::list< std::pair<std::string, std::string> >::iterator Names = NameList.begin(); Names != NameList.end(); ++Names ) for( std::list< std::pair<std::string, std::string> >::iterator Names = NameList.begin(); Names != NameList.end(); ++Names )
{ {
Menu += "<li><a href='" + BaseURL + WebPlugin->GetName().c_str() + "/" + (*Names).second + "'>" + (*Names).first + "</a></li>"; Menu += "<li><a href='" + BaseURL + WebPlugin->GetWebTitle().c_str() + "/" + (*Names).second + "'>" + (*Names).first + "</a></li>";
} }
} }
@ -190,11 +190,11 @@ void cWebAdmin::Request_Handler(webserver::http_request* r)
{ {
for (PluginList::iterator itr = WebAdmin->m_Plugins.begin(); itr != WebAdmin->m_Plugins.end(); ++itr) for (PluginList::iterator itr = WebAdmin->m_Plugins.begin(); itr != WebAdmin->m_Plugins.end(); ++itr)
{ {
if( (*itr)->GetName() == Split[1] ) if ((*itr)->GetWebTitle() == Split[1])
{ {
Content = (*itr)->HandleWebRequest(&Request); Content = (*itr)->HandleWebRequest(&Request);
cWebPlugin * WebPlugin = *itr; cWebPlugin * WebPlugin = *itr;
FoundPlugin = WebPlugin->GetName(); FoundPlugin = WebPlugin->GetWebTitle();
AString TabName = WebPlugin->GetTabNameForRequest(&Request).first; AString TabName = WebPlugin->GetTabNameForRequest(&Request).first;
if (!TabName.empty()) if (!TabName.empty())
{ {

View File

@ -12,9 +12,11 @@
cWebPlugin::cWebPlugin() cWebPlugin::cWebPlugin()
{ {
LOG("cWebPlugin::cWebPlugin()");
cWebAdmin * WebAdmin = cRoot::Get()->GetWebAdmin(); cWebAdmin * WebAdmin = cRoot::Get()->GetWebAdmin();
if( WebAdmin ) WebAdmin->AddPlugin( this ); if (WebAdmin != NULL)
{
WebAdmin->AddPlugin(this);
}
} }
@ -23,9 +25,11 @@ cWebPlugin::cWebPlugin()
cWebPlugin::~cWebPlugin() cWebPlugin::~cWebPlugin()
{ {
LOG("~cWebPlugin::cWebPlugin()");
cWebAdmin * WebAdmin = cRoot::Get()->GetWebAdmin(); cWebAdmin * WebAdmin = cRoot::Get()->GetWebAdmin();
if( WebAdmin ) WebAdmin->RemovePlugin( this ); if (WebAdmin != NULL)
{
WebAdmin->RemovePlugin(this);
}
for (TabList::iterator itr = m_Tabs.begin(); itr != m_Tabs.end(); ++itr) for (TabList::iterator itr = m_Tabs.begin(); itr != m_Tabs.end(); ++itr)
{ {
@ -38,7 +42,7 @@ cWebPlugin::~cWebPlugin()
std::list< std::pair<AString, AString> > cWebPlugin::GetTabNames() std::list<std::pair<AString, AString> > cWebPlugin::GetTabNames(void)
{ {
std::list< std::pair< AString, AString > > NameList; std::list< std::pair< AString, AString > > NameList;
for( TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr ) for( TabList::iterator itr = GetTabs().begin(); itr != GetTabs().end(); ++itr )

View File

@ -16,7 +16,7 @@ public:
cWebPlugin(); cWebPlugin();
virtual ~cWebPlugin(); virtual ~cWebPlugin();
virtual const AString & GetName(void) const = 0; virtual const AString & GetWebTitle(void) const = 0;
// tolua_begin // tolua_begin
virtual AString HandleWebRequest( HTTPRequest * a_Request ) = 0; virtual AString HandleWebRequest( HTTPRequest * a_Request ) = 0;

View File

@ -174,50 +174,6 @@ protected:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// cWorld: // cWorld:
cWorld* cWorld::GetWorld()
{
LOGWARN("WARNING: Using deprecated function cWorld::GetWorld() use cRoot::Get()->GetDefaultWorld() instead!");
return cRoot::Get()->GetDefaultWorld();
}
cWorld::~cWorld()
{
{
cCSLock Lock(m_CSEntities);
while( m_AllEntities.begin() != m_AllEntities.end() )
{
cEntity* Entity = *m_AllEntities.begin();
m_AllEntities.remove( Entity );
if ( !Entity->IsDestroyed() )
{
Entity->Destroy();
}
delete Entity;
}
}
delete m_SimulatorManager;
delete m_SandSimulator;
delete m_WaterSimulator;
delete m_LavaSimulator;
delete m_FireSimulator;
delete m_RedstoneSimulator;
UnloadUnusedChunks();
m_Storage.WaitForFinish();
delete m_ChunkMap;
}
cWorld::cWorld(const AString & a_WorldName) : cWorld::cWorld(const AString & a_WorldName) :
m_WorldAgeSecs(0), m_WorldAgeSecs(0),
m_TimeOfDaySecs(0), m_TimeOfDaySecs(0),
@ -317,6 +273,40 @@ cWorld::cWorld(const AString & a_WorldName) :
cWorld::~cWorld()
{
{
cCSLock Lock(m_CSEntities);
while( m_AllEntities.begin() != m_AllEntities.end() )
{
cEntity* Entity = *m_AllEntities.begin();
m_AllEntities.remove( Entity );
if ( !Entity->IsDestroyed() )
{
Entity->Destroy();
}
delete Entity;
}
}
delete m_SimulatorManager;
delete m_SandSimulator;
delete m_WaterSimulator;
delete m_LavaSimulator;
delete m_FireSimulator;
delete m_RedstoneSimulator;
UnloadUnusedChunks();
m_Storage.WaitForFinish();
delete m_ChunkMap;
}
void cWorld::SetWeather(eWeather a_Weather) void cWorld::SetWeather(eWeather a_Weather)
{ {
switch (a_Weather) switch (a_Weather)
@ -1071,7 +1061,7 @@ void cWorld::SetBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_Bloc
m_ChunkMap->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta); m_ChunkMap->SetBlock(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
GetSimulatorManager()->WakeUp(a_BlockX, a_BlockY, a_BlockZ); GetSimulatorManager()->WakeUp(a_BlockX, a_BlockY, a_BlockZ);
BlockHandler(a_BlockType)->OnPlaced(this, a_BlockX, a_BlockY, a_BlockZ, a_BlockMeta); BlockHandler(a_BlockType)->OnPlaced(this, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
} }

View File

@ -59,8 +59,6 @@ class cWorld //tolua_export
{ // tolua_export { // tolua_export
public: public:
OBSOLETE static cWorld * GetWorld();
// tolua_begin // tolua_begin
/// Return time in seconds /// Return time in seconds
@ -70,11 +68,6 @@ public:
return 0; return 0;
} }
long long GetWorldTime(void) const // OBSOLETE, use GetWorldAge() instead!
{
LOGWARNING("cWorld:GetWorldTime() is obsolete, use GetWorldAge() or GetTimeOfDay() instead");
return m_WorldAge;
}
Int64 GetWorldAge(void) const { return m_WorldAge; } Int64 GetWorldAge(void) const { return m_WorldAge; }
Int64 GetTimeOfDay(void) const { return m_TimeOfDay; } Int64 GetTimeOfDay(void) const { return m_TimeOfDay; }

View File

@ -108,8 +108,8 @@ protected:
void AddItem(const cItem * a_Item, int a_Slot) void AddItem(const cItem * a_Item, int a_Slot)
{ {
m_Writer.BeginCompound(""); m_Writer.BeginCompound("");
m_Writer.AddShort("id", (short)(a_Item->m_ItemID)); m_Writer.AddShort("id", (short)(a_Item->m_ItemType));
m_Writer.AddShort("Damage", a_Item->m_ItemHealth); m_Writer.AddShort("Damage", a_Item->m_ItemDamage);
m_Writer.AddByte ("Count", a_Item->m_ItemCount); m_Writer.AddByte ("Count", a_Item->m_ItemCount);
m_Writer.AddByte ("Slot", (unsigned char)a_Slot); m_Writer.AddByte ("Slot", (unsigned char)a_Slot);
m_Writer.EndCompound(); m_Writer.EndCompound();
@ -804,13 +804,13 @@ void cWSSAnvil::LoadChestFromNBT(cBlockEntityList & a_BlockEntities, const cPars
{ {
continue; continue;
} }
Item.m_ItemID = (ENUM_ITEM_ID)(a_NBT.GetShort(ID)); Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID));
int Damage = a_NBT.FindChildByName(Child, "Damage"); int Damage = a_NBT.FindChildByName(Child, "Damage");
if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short)) if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short))
{ {
continue; continue;
} }
Item.m_ItemHealth = a_NBT.GetShort(Damage); Item.m_ItemDamage = a_NBT.GetShort(Damage);
int Count = a_NBT.FindChildByName(Child, "Count"); int Count = a_NBT.FindChildByName(Child, "Count");
if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte)) if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte))
{ {
@ -853,13 +853,13 @@ void cWSSAnvil::LoadDispenserFromNBT(cBlockEntityList & a_BlockEntities, const c
{ {
continue; continue;
} }
Item.m_ItemID = (ENUM_ITEM_ID)(a_NBT.GetShort(ID)); Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID));
int Damage = a_NBT.FindChildByName(Child, "Damage"); int Damage = a_NBT.FindChildByName(Child, "Damage");
if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short)) if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short))
{ {
continue; continue;
} }
Item.m_ItemHealth = a_NBT.GetShort(Damage); Item.m_ItemDamage = a_NBT.GetShort(Damage);
int Count = a_NBT.FindChildByName(Child, "Count"); int Count = a_NBT.FindChildByName(Child, "Count");
if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte)) if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte))
{ {
@ -902,13 +902,13 @@ void cWSSAnvil::LoadFurnaceFromNBT(cBlockEntityList & a_BlockEntities, const cPa
{ {
continue; continue;
} }
Item.m_ItemID = (ENUM_ITEM_ID)(a_NBT.GetShort(ID)); Item.m_ItemType = (ENUM_ITEM_ID)(a_NBT.GetShort(ID));
int Damage = a_NBT.FindChildByName(Child, "Damage"); int Damage = a_NBT.FindChildByName(Child, "Damage");
if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short)) if ((Damage < 0) || (a_NBT.GetType(Damage) != TAG_Short))
{ {
continue; continue;
} }
Item.m_ItemHealth = a_NBT.GetShort(Damage); Item.m_ItemDamage = a_NBT.GetShort(Damage);
int Count = a_NBT.FindChildByName(Child, "Count"); int Count = a_NBT.FindChildByName(Child, "Count");
if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte)) if ((Count < 0) || (a_NBT.GetType(Count) != TAG_Byte))
{ {

View File

@ -161,7 +161,7 @@ void BindSquirrel(HSQUIRRELVM vm)
ConstTable().Enum("Hook", Enumeration() ConstTable().Enum("Hook", Enumeration()
.Const("Tick", cPluginManager::HOOK_TICK) .Const("Tick", cPluginManager::HOOK_TICK)
.Const("Chat", cPluginManager::HOOK_CHAT) .Const("Chat", cPluginManager::HOOK_CHAT)
.Const("CollectItem", cPluginManager::HOOK_COLLECT_ITEM) .Const("CollectPickup", cPluginManager::HOOK_COLLECT_PICKUP)
.Const("BlockDig", cPluginManager::HOOK_BLOCK_DIG) .Const("BlockDig", cPluginManager::HOOK_BLOCK_DIG)
.Const("BlockPlace", cPluginManager::HOOK_BLOCK_PLACE) .Const("BlockPlace", cPluginManager::HOOK_BLOCK_PLACE)
.Const("Disconnect", cPluginManager::HOOK_DISCONNECT) .Const("Disconnect", cPluginManager::HOOK_DISCONNECT)