Merged in the Projectiles branch.
Although the projectiles are not yet finished, the branch has several bugfixes that are needed in master as well.
This commit is contained in:
commit
c28ccdc9d5
@ -45,6 +45,7 @@ function Initialize(Plugin)
|
|||||||
PluginManager:BindCommand("/spidey", "debuggers", HandleSpideyCmd, "- Shoots a line of web blocks until it hits non-air");
|
PluginManager:BindCommand("/spidey", "debuggers", HandleSpideyCmd, "- Shoots a line of web blocks until it hits non-air");
|
||||||
PluginManager:BindCommand("/ench", "debuggers", HandleEnchCmd, "- Provides an instant dummy enchantment window");
|
PluginManager:BindCommand("/ench", "debuggers", HandleEnchCmd, "- Provides an instant dummy enchantment window");
|
||||||
PluginManager:BindCommand("/fs", "debuggers", HandleFoodStatsCmd, "- Turns regular foodstats message on or off");
|
PluginManager:BindCommand("/fs", "debuggers", HandleFoodStatsCmd, "- Turns regular foodstats message on or off");
|
||||||
|
PluginManager:BindCommand("/arr", "debuggers", HandleArrowCmd, "- Creates an arrow going away from the player");
|
||||||
|
|
||||||
-- Enable the following line for BlockArea / Generator interface testing:
|
-- Enable the following line for BlockArea / Generator interface testing:
|
||||||
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
|
-- PluginManager:AddHook(Plugin, cPluginManager.HOOK_CHUNK_GENERATED);
|
||||||
@ -794,6 +795,7 @@ function HandleEnchCmd(a_Split, a_Player)
|
|||||||
Wnd:SetProperty(0, 10);
|
Wnd:SetProperty(0, 10);
|
||||||
Wnd:SetProperty(1, 15);
|
Wnd:SetProperty(1, 15);
|
||||||
Wnd:SetProperty(2, 25);
|
Wnd:SetProperty(2, 25);
|
||||||
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -802,6 +804,22 @@ end
|
|||||||
|
|
||||||
function HandleFoodStatsCmd(a_Split, a_Player)
|
function HandleFoodStatsCmd(a_Split, a_Player)
|
||||||
g_ShowFoodStats = not(g_ShowFoodStats);
|
g_ShowFoodStats = not(g_ShowFoodStats);
|
||||||
|
return true;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function HandleArrowCmd(a_Split, a_Player)
|
||||||
|
local World = a_Player:GetWorld();
|
||||||
|
local Pos = a_Player:GetEyePosition();
|
||||||
|
local Speed = a_Player:GetLookVector();
|
||||||
|
Speed:Normalize();
|
||||||
|
Pos = Pos + Speed;
|
||||||
|
|
||||||
|
World:CreateProjectile(Pos.x, Pos.y, Pos.z, cProjectileEntity.pkArrow, a_Player, Speed * 10);
|
||||||
|
return true;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -1159,6 +1159,10 @@
|
|||||||
RelativePath="..\source\Entities\Player.h"
|
RelativePath="..\source\Entities\Player.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\source\Entities\ProjectileEntity.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\source\Entities\ProjectileEntity.h"
|
RelativePath="..\source\Entities\ProjectileEntity.h"
|
||||||
>
|
>
|
||||||
@ -2235,6 +2239,10 @@
|
|||||||
RelativePath="..\source\items\ItemBed.h"
|
RelativePath="..\source\items\ItemBed.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\source\Items\ItemBow.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\source\Items\ItemBrewingStand.h"
|
RelativePath="..\source\Items\ItemBrewingStand.h"
|
||||||
>
|
>
|
||||||
|
@ -27,6 +27,8 @@ $cfile "ClientHandle.h"
|
|||||||
$cfile "Entities/Entity.h"
|
$cfile "Entities/Entity.h"
|
||||||
$cfile "Entities/Pawn.h"
|
$cfile "Entities/Pawn.h"
|
||||||
$cfile "Entities/Player.h"
|
$cfile "Entities/Player.h"
|
||||||
|
$cfile "Entities/Pickup.h"
|
||||||
|
$cfile "Entities/ProjectileEntity.h"
|
||||||
$cfile "PluginManager.h"
|
$cfile "PluginManager.h"
|
||||||
$cfile "Plugin.h"
|
$cfile "Plugin.h"
|
||||||
$cfile "PluginLua.h"
|
$cfile "PluginLua.h"
|
||||||
@ -45,7 +47,6 @@ $cfile "BlockEntities/DropperEntity.h"
|
|||||||
$cfile "BlockEntities/FurnaceEntity.h"
|
$cfile "BlockEntities/FurnaceEntity.h"
|
||||||
$cfile "WebAdmin.h"
|
$cfile "WebAdmin.h"
|
||||||
$cfile "WebPlugin.h"
|
$cfile "WebPlugin.h"
|
||||||
$cfile "Entities/Pickup.h"
|
|
||||||
$cfile "Root.h"
|
$cfile "Root.h"
|
||||||
$cfile "Vector3f.h"
|
$cfile "Vector3f.h"
|
||||||
$cfile "Vector3d.h"
|
$cfile "Vector3d.h"
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
** Lua binding: AllToLua
|
** Lua binding: AllToLua
|
||||||
** Generated automatically by tolua++-1.0.92 on 08/27/13 08:55:57.
|
** Generated automatically by tolua++-1.0.92 on 08/30/13 14:30:25.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Exported function */
|
/* Exported function */
|
||||||
|
@ -367,7 +367,9 @@ enum ENUM_ITEM_ID
|
|||||||
// Keep these two as the last values of the disc list, without a number - they will get their correct number assigned automagically by C++
|
// 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!
|
// 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_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
|
E_ITEM_LAST_DISC = E_ITEM_LAST_DISC_PLUS_ONE - 1, ///< Maximum disc itemtype number used
|
||||||
|
|
||||||
|
E_ITEM_LAST = E_ITEM_LAST_DISC, ///< Maximum valid ItemType
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@ public:
|
|||||||
/** Called on each block encountered along the path, including the first block (path start)
|
/** Called on each block encountered along the path, including the first block (path start)
|
||||||
When this callback returns true, the tracing is aborted.
|
When this callback returns true, the tracing is aborted.
|
||||||
*/
|
*/
|
||||||
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) = 0;
|
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) = 0;
|
||||||
|
|
||||||
/** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded
|
/** Called on each block encountered along the path, including the first block (path start), if chunk data is not loaded
|
||||||
When this callback returns true, the tracing is aborted.
|
When this callback returns true, the tracing is aborted.
|
||||||
*/
|
*/
|
||||||
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) { return false; }
|
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) { return false; }
|
||||||
|
|
||||||
/** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
|
/** Called when the path goes out of world, either below (a_BlockY < 0) or above (a_BlockY >= cChunkDef::Height)
|
||||||
The coords specify the exact point at which the path exited the world.
|
The coords specify the exact point at which the path exited the world.
|
||||||
|
@ -576,8 +576,8 @@ void cClientHandle::HandleLeftClick(int a_BlockX, int a_BlockY, int a_BlockZ, ch
|
|||||||
// A plugin doesn't agree with the action. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
|
// A plugin doesn't agree with the action. The plugin itself is responsible for handling the consequences (possible inventory mismatch)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ItemHandler->OnItemShoot(m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace);
|
||||||
}
|
}
|
||||||
LOGINFO("%s: Status SHOOT not implemented", __FUNCTION__);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,16 +790,16 @@ void cClientHandle::HandleRightClick(int a_BlockX, int a_BlockY, int a_BlockZ, c
|
|||||||
BLOCKTYPE BlockType;
|
BLOCKTYPE BlockType;
|
||||||
NIBBLETYPE BlockMeta;
|
NIBBLETYPE BlockMeta;
|
||||||
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
|
World->GetBlockTypeMeta(a_BlockX, a_BlockY, a_BlockZ, BlockType, BlockMeta);
|
||||||
cBlockHandler * Handler = cBlockHandler::GetBlockHandler(BlockType);
|
cBlockHandler * BlockHandler = cBlockHandler::GetBlockHandler(BlockType);
|
||||||
|
|
||||||
if (Handler->IsUseable() && !m_Player->IsCrouched())
|
if (BlockHandler->IsUseable() && !m_Player->IsCrouched())
|
||||||
{
|
{
|
||||||
if (PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
|
if (PlgMgr->CallHookPlayerUsingBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta))
|
||||||
{
|
{
|
||||||
// A plugin doesn't agree with using the block, abort
|
// A plugin doesn't agree with using the block, abort
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Handler->OnUse(World, m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ);
|
BlockHandler->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);
|
PlgMgr->CallHookPlayerUsedBlock(*m_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace, a_CursorX, a_CursorY, a_CursorZ, BlockType, BlockMeta);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -144,6 +144,10 @@ bool cEntity::Initialize(cWorld * a_World)
|
|||||||
m_World->AddEntity(this);
|
m_World->AddEntity(this);
|
||||||
|
|
||||||
cPluginManager::Get()->CallHookSpawnedEntity(*a_World, *this);
|
cPluginManager::Get()->CallHookSpawnedEntity(*a_World, *this);
|
||||||
|
|
||||||
|
// Spawn the entity on the clients:
|
||||||
|
a_World->BroadcastSpawnEntity(*this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,7 +481,7 @@ void cEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
// TODO Add collision detection with entities.
|
// TODO Add collision detection with entities.
|
||||||
a_Dt /= 1000;
|
a_Dt /= 1000; // Convert from msec to sec
|
||||||
Vector3d NextPos = Vector3d(GetPosX(),GetPosY(),GetPosZ());
|
Vector3d NextPos = Vector3d(GetPosX(),GetPosY(),GetPosZ());
|
||||||
Vector3d NextSpeed = Vector3d(GetSpeedX(),GetSpeedY(),GetSpeedZ());
|
Vector3d NextSpeed = Vector3d(GetSpeedX(),GetSpeedY(),GetSpeedZ());
|
||||||
int BlockX = (int) floor(NextPos.x);
|
int BlockX = (int) floor(NextPos.x);
|
||||||
@ -493,7 +497,7 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we got the correct chunk and a valid one. No one ever knows...
|
// Make sure we got the correct chunk and a valid one. No one ever knows...
|
||||||
cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX,BlockZ);
|
cChunk * NextChunk = a_Chunk.GetNeighborChunk(BlockX, BlockZ);
|
||||||
if (NextChunk != NULL)
|
if (NextChunk != NULL)
|
||||||
{
|
{
|
||||||
int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
|
int RelBlockX = BlockX - (NextChunk->GetPosX() * cChunkDef::Width);
|
||||||
@ -512,11 +516,12 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Push out entity.
|
// Push out entity.
|
||||||
m_bOnGround = true;
|
m_bOnGround = true;
|
||||||
NextPos.y += 0.2;
|
NextPos.y += 0.2;
|
||||||
LOGD("Entity #%d (%s) is inside a block at {%d,%d,%d}",
|
LOGD("Entity #%d (%s) is inside a block at {%d, %d, %d}",
|
||||||
m_UniqueID, GetClass(), BlockX, BlockY, BlockZ);
|
m_UniqueID, GetClass(), BlockX, BlockY, BlockZ
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_bOnGround)
|
if (!m_bOnGround)
|
||||||
@ -524,34 +529,40 @@ void cEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
|||||||
float fallspeed;
|
float fallspeed;
|
||||||
if (IsBlockWater(BlockIn))
|
if (IsBlockWater(BlockIn))
|
||||||
{
|
{
|
||||||
fallspeed = -3.0f * a_Dt; //Fall slower in water.
|
fallspeed = m_Gravity * a_Dt / 3; // Fall 3x slower in water.
|
||||||
}
|
}
|
||||||
else if (BlockIn == E_BLOCK_COBWEB)
|
else if (BlockIn == E_BLOCK_COBWEB)
|
||||||
{
|
{
|
||||||
NextSpeed.y *= 0.05; //Reduce overall falling speed
|
NextSpeed.y *= 0.05; // Reduce overall falling speed
|
||||||
fallspeed = 0; //No falling.
|
fallspeed = 0; // No falling.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Normal gravity
|
// Normal gravity
|
||||||
fallspeed = m_Gravity * a_Dt;
|
fallspeed = m_Gravity * a_Dt;
|
||||||
}
|
}
|
||||||
NextSpeed.y += fallspeed;
|
NextSpeed.y += fallspeed;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Friction
|
// Friction
|
||||||
if (NextSpeed.SqrLength() > 0.0004f)
|
if (NextSpeed.SqrLength() > 0.0004f)
|
||||||
{
|
{
|
||||||
NextSpeed.x *= 0.7f/(1+a_Dt);
|
NextSpeed.x *= 0.7f / (1 + a_Dt);
|
||||||
if ( fabs(NextSpeed.x) < 0.05 ) NextSpeed.x = 0;
|
if (fabs(NextSpeed.x) < 0.05)
|
||||||
NextSpeed.z *= 0.7f/(1+a_Dt);
|
{
|
||||||
if ( fabs(NextSpeed.z) < 0.05 ) NextSpeed.z = 0;
|
NextSpeed.x = 0;
|
||||||
|
}
|
||||||
|
NextSpeed.z *= 0.7f / (1 + a_Dt);
|
||||||
|
if (fabs(NextSpeed.z) < 0.05)
|
||||||
|
{
|
||||||
|
NextSpeed.z = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
|
// Adjust X and Z speed for COBWEB temporary. This speed modification should be handled inside block handlers since we
|
||||||
//might have different speed modifiers according to terrain.
|
// might have different speed modifiers according to terrain.
|
||||||
if (BlockIn == E_BLOCK_COBWEB)
|
if (BlockIn == E_BLOCK_COBWEB)
|
||||||
{
|
{
|
||||||
NextSpeed.x *= 0.25;
|
NextSpeed.x *= 0.25;
|
||||||
@ -1028,9 +1039,9 @@ void cEntity::SetMass(double a_Mass)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//Make sure that mass is not zero. 1g is the default because we
|
// Make sure that mass is not zero. 1g is the default because we
|
||||||
//have to choose a number. It's perfectly legal to have a mass
|
// have to choose a number. It's perfectly legal to have a mass
|
||||||
//less than 1g as long as is NOT equal or less than zero.
|
// less than 1g as long as is NOT equal or less than zero.
|
||||||
m_Mass = 0.001;
|
m_Mass = 0.001;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,12 +90,13 @@ public:
|
|||||||
etPlayer,
|
etPlayer,
|
||||||
etPickup,
|
etPickup,
|
||||||
etMonster,
|
etMonster,
|
||||||
etMob = etMonster, // DEPRECATED, use etMonster instead!
|
|
||||||
etFallingBlock,
|
etFallingBlock,
|
||||||
etMinecart,
|
etMinecart,
|
||||||
etTNT,
|
etTNT,
|
||||||
|
etProjectile,
|
||||||
|
|
||||||
// DEPRECATED older constants, left over for compatibility reasons (plugins)
|
// DEPRECATED older constants, left over for compatibility reasons (plugins)
|
||||||
|
etMob = etMonster, // DEPRECATED, use etMonster instead!
|
||||||
eEntityType_Entity = etEntity,
|
eEntityType_Entity = etEntity,
|
||||||
eEntityType_Player = etPlayer,
|
eEntityType_Player = etPlayer,
|
||||||
eEntityType_Pickup = etPickup,
|
eEntityType_Pickup = etPickup,
|
||||||
@ -162,7 +163,7 @@ public:
|
|||||||
void SetPosY (double a_PosY);
|
void SetPosY (double a_PosY);
|
||||||
void SetPosZ (double a_PosZ);
|
void SetPosZ (double a_PosZ);
|
||||||
void SetPosition(double a_PosX, double a_PosY, double a_PosZ);
|
void SetPosition(double a_PosX, double a_PosY, double a_PosZ);
|
||||||
void SetPosition(const Vector3d & a_Pos) { SetPosition(a_Pos.x,a_Pos.y,a_Pos.z);}
|
void SetPosition(const Vector3d & a_Pos) { SetPosition(a_Pos.x, a_Pos.y, a_Pos.z); }
|
||||||
void SetRot (const Vector3f & a_Rot);
|
void SetRot (const Vector3f & a_Rot);
|
||||||
void SetRotation(double a_Rotation);
|
void SetRotation(double a_Rotation);
|
||||||
void SetPitch (double a_Pitch);
|
void SetPitch (double a_Pitch);
|
||||||
|
@ -22,20 +22,6 @@ cFallingBlock::cFallingBlock(const Vector3i & a_BlockPosition, BLOCKTYPE a_Block
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cFallingBlock::Initialize(cWorld * a_World)
|
|
||||||
{
|
|
||||||
if (super::Initialize(a_World))
|
|
||||||
{
|
|
||||||
a_World->BroadcastSpawnEntity(*this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle)
|
void cFallingBlock::SpawnOn(cClientHandle & a_ClientHandle)
|
||||||
{
|
{
|
||||||
a_ClientHandle.SendSpawnFallingBlock(*this);
|
a_ClientHandle.SendSpawnFallingBlock(*this);
|
||||||
|
@ -29,7 +29,6 @@ public:
|
|||||||
NIBBLETYPE GetBlockMeta(void) const { return m_BlockMeta; }
|
NIBBLETYPE GetBlockMeta(void) const { return m_BlockMeta; }
|
||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual bool Initialize(cWorld * a_World) override;
|
|
||||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
|
@ -22,20 +22,6 @@ cMinecart::cMinecart(ePayload a_Payload, double a_X, double a_Y, double a_Z) :
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cMinecart::Initialize(cWorld * a_World)
|
|
||||||
{
|
|
||||||
if (super::Initialize(a_World))
|
|
||||||
{
|
|
||||||
a_World->BroadcastSpawnEntity(*this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cMinecart::SpawnOn(cClientHandle & a_ClientHandle)
|
void cMinecart::SpawnOn(cClientHandle & a_ClientHandle)
|
||||||
{
|
{
|
||||||
char Type = 0;
|
char Type = 0;
|
||||||
|
@ -35,7 +35,6 @@ public:
|
|||||||
} ;
|
} ;
|
||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual bool Initialize(cWorld * a_World) override;
|
|
||||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
|
@ -40,20 +40,6 @@ cPickup::cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPickup::Initialize(cWorld * a_World)
|
|
||||||
{
|
|
||||||
if (super::Initialize(a_World))
|
|
||||||
{
|
|
||||||
a_World->BroadcastSpawnEntity(*this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPickup::SpawnOn(cClientHandle & a_Client)
|
void cPickup::SpawnOn(cClientHandle & a_Client)
|
||||||
{
|
{
|
||||||
a_Client.SendPickupSpawn(*this);
|
a_Client.SendPickupSpawn(*this);
|
||||||
|
@ -26,8 +26,6 @@ public:
|
|||||||
|
|
||||||
cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem & a_Item, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f); // tolua_export
|
cPickup(int a_MicroPosX, int a_MicroPosY, int a_MicroPosZ, const cItem & a_Item, float a_SpeedX = 0.f, float a_SpeedY = 0.f, float a_SpeedZ = 0.f); // tolua_export
|
||||||
|
|
||||||
virtual bool Initialize(cWorld * a_World) override;
|
|
||||||
|
|
||||||
cItem & GetItem(void) {return m_Item; } // tolua_export
|
cItem & GetItem(void) {return m_Item; } // tolua_export
|
||||||
const cItem & GetItem(void) const {return m_Item; }
|
const cItem & GetItem(void) const {return m_Item; }
|
||||||
|
|
||||||
|
@ -64,6 +64,8 @@ cPlayer::cPlayer(cClientHandle* a_Client, const AString & a_PlayerName)
|
|||||||
, m_IsSwimming(false)
|
, m_IsSwimming(false)
|
||||||
, m_IsSubmerged(false)
|
, m_IsSubmerged(false)
|
||||||
, m_EatingFinishTick(-1)
|
, m_EatingFinishTick(-1)
|
||||||
|
, m_IsChargingBow(false)
|
||||||
|
, m_BowCharge(0)
|
||||||
{
|
{
|
||||||
LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
|
LOGD("Created a player object for \"%s\" @ \"%s\" at %p, ID %d",
|
||||||
a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
|
a_PlayerName.c_str(), a_Client->GetIPString().c_str(),
|
||||||
@ -214,6 +216,13 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
// Handle air drowning stuff
|
// Handle air drowning stuff
|
||||||
HandleAir();
|
HandleAir();
|
||||||
|
|
||||||
|
// Handle charging the bow:
|
||||||
|
if (m_IsChargingBow)
|
||||||
|
{
|
||||||
|
m_BowCharge += 1;
|
||||||
|
LOGD("Player \"%s\" charging bow: %d", m_PlayerName.c_str(), m_BowCharge);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_bDirtyPosition)
|
if (m_bDirtyPosition)
|
||||||
{
|
{
|
||||||
// Apply food exhaustion from movement:
|
// Apply food exhaustion from movement:
|
||||||
@ -253,6 +262,41 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPlayer::StartChargingBow(void)
|
||||||
|
{
|
||||||
|
LOGD("Player \"%s\" started charging their bow", m_PlayerName.c_str());
|
||||||
|
m_IsChargingBow = true;
|
||||||
|
m_BowCharge = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cPlayer::FinishChargingBow(void)
|
||||||
|
{
|
||||||
|
LOGD("Player \"%s\" finished charging their bow at a charge of %d", m_PlayerName.c_str(), m_BowCharge);
|
||||||
|
int res = m_BowCharge;
|
||||||
|
m_IsChargingBow = false;
|
||||||
|
m_BowCharge = 0;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cPlayer::CancelChargingBow(void)
|
||||||
|
{
|
||||||
|
LOGD("Player \"%s\" cancelled charging their bow at a charge of %d", m_PlayerName.c_str(), m_BowCharge);
|
||||||
|
m_IsChargingBow = false;
|
||||||
|
m_BowCharge = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cPlayer::SetTouchGround(bool a_bTouchGround)
|
void cPlayer::SetTouchGround(bool a_bTouchGround)
|
||||||
{
|
{
|
||||||
// If just
|
// If just
|
||||||
|
@ -63,6 +63,18 @@ public:
|
|||||||
/// Returns the currently equipped boots; empty item if none
|
/// Returns the currently equipped boots; empty item if none
|
||||||
virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); }
|
virtual cItem GetEquippedBoots(void) const override { return m_Inventory.GetEquippedBoots(); }
|
||||||
|
|
||||||
|
/// Starts charging the equipped bow
|
||||||
|
void StartChargingBow(void);
|
||||||
|
|
||||||
|
/// Finishes charging the current bow. Returns the number of ticks for which the bow has been charged
|
||||||
|
int FinishChargingBow(void);
|
||||||
|
|
||||||
|
/// Cancels the current bow charging
|
||||||
|
void CancelChargingBow(void);
|
||||||
|
|
||||||
|
/// Returns true if the player is currently charging the bow
|
||||||
|
bool IsChargingBox(void) const { return m_IsChargingBow; }
|
||||||
|
|
||||||
void SetTouchGround( bool a_bTouchGround );
|
void SetTouchGround( bool a_bTouchGround );
|
||||||
inline void SetStance( const double a_Stance ) { m_Stance = a_Stance; }
|
inline void SetStance( const double a_Stance ) { m_Stance = a_Stance; }
|
||||||
double GetEyeHeight(void) const; // tolua_export
|
double GetEyeHeight(void) const; // tolua_export
|
||||||
@ -352,6 +364,9 @@ protected:
|
|||||||
/// The world tick in which eating will be finished. -1 if not eating
|
/// The world tick in which eating will be finished. -1 if not eating
|
||||||
Int64 m_EatingFinishTick;
|
Int64 m_EatingFinishTick;
|
||||||
|
|
||||||
|
bool m_IsChargingBow;
|
||||||
|
int m_BowCharge;
|
||||||
|
|
||||||
virtual void Destroyed(void);
|
virtual void Destroyed(void);
|
||||||
|
|
||||||
/// Filters out damage for creative mode
|
/// Filters out damage for creative mode
|
||||||
|
296
source/Entities/ProjectileEntity.cpp
Normal file
296
source/Entities/ProjectileEntity.cpp
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
|
||||||
|
// ProjectileEntity.cpp
|
||||||
|
|
||||||
|
// Implements the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types
|
||||||
|
|
||||||
|
#include "Globals.h"
|
||||||
|
#include "ProjectileEntity.h"
|
||||||
|
#include "../ClientHandle.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "../LineBlockTracer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cProjectileTracerCallback:
|
||||||
|
|
||||||
|
class cProjectileTracerCallback :
|
||||||
|
public cBlockTracer::cCallbacks
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cProjectileTracerCallback(cProjectileEntity * a_Projectile) :
|
||||||
|
m_Projectile(a_Projectile)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cProjectileEntity * m_Projectile;
|
||||||
|
|
||||||
|
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
|
||||||
|
{
|
||||||
|
if (g_BlockIsSolid[a_BlockType])
|
||||||
|
{
|
||||||
|
// The projectile hit a solid block
|
||||||
|
m_Projectile->OnHitSolidBlock(a_BlockX, a_BlockY, a_BlockZ, a_EntryFace);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convey some special effects from special blocks:
|
||||||
|
switch (a_BlockType)
|
||||||
|
{
|
||||||
|
case E_BLOCK_LAVA:
|
||||||
|
case E_BLOCK_STATIONARY_LAVA:
|
||||||
|
{
|
||||||
|
m_Projectile->StartBurning(30);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_BLOCK_WATER:
|
||||||
|
case E_BLOCK_STATIONARY_WATER:
|
||||||
|
{
|
||||||
|
m_Projectile->StopBurning();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // switch (a_BlockType)
|
||||||
|
|
||||||
|
// Continue tracing
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cProjectileEntity:
|
||||||
|
|
||||||
|
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height) :
|
||||||
|
super(etProjectile, a_X, a_Y, a_Z, a_Width, a_Height),
|
||||||
|
m_ProjectileKind(a_Kind),
|
||||||
|
m_Creator(a_Creator),
|
||||||
|
m_IsInGround(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cProjectileEntity::cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height) :
|
||||||
|
super(etProjectile, a_Pos.x, a_Pos.y, a_Pos.z, a_Width, a_Height),
|
||||||
|
m_ProjectileKind(a_Kind),
|
||||||
|
m_Creator(a_Creator),
|
||||||
|
m_IsInGround(false)
|
||||||
|
{
|
||||||
|
SetSpeed(a_Speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cProjectileEntity * cProjectileEntity::Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed)
|
||||||
|
{
|
||||||
|
Vector3d Speed;
|
||||||
|
if (a_Speed != NULL)
|
||||||
|
{
|
||||||
|
Speed = *a_Speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (a_Kind)
|
||||||
|
{
|
||||||
|
case pkArrow: return new cArrowEntity(a_Creator, a_X, a_Y, a_Z, Speed);
|
||||||
|
// TODO: the rest
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGWARNING("%s: Unknown kind: %d", __FUNCTION__, a_Kind);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cProjectileEntity::OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace)
|
||||||
|
{
|
||||||
|
// TODO: Set proper position based on what face was hit
|
||||||
|
switch (a_BlockFace)
|
||||||
|
{
|
||||||
|
case BLOCK_FACE_TOP: SetPosition(0.5 + a_BlockX, 1.0 + a_BlockY, 0.5 + a_BlockZ); break;
|
||||||
|
case BLOCK_FACE_BOTTOM: SetPosition(0.5 + a_BlockX, a_BlockY, 0.5 + a_BlockZ); break;
|
||||||
|
case BLOCK_FACE_EAST: SetPosition( a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break;
|
||||||
|
case BLOCK_FACE_WEST: SetPosition(1.0 + a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break;
|
||||||
|
case BLOCK_FACE_NORTH: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, 1.0 + a_BlockZ); break;
|
||||||
|
case BLOCK_FACE_SOUTH: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, a_BlockZ); break;
|
||||||
|
case BLOCK_FACE_NONE: SetPosition(0.5 + a_BlockX, 0.5 + a_BlockY, 0.5 + a_BlockZ); break;
|
||||||
|
}
|
||||||
|
SetSpeed(0, 0, 0);
|
||||||
|
|
||||||
|
// DEBUG:
|
||||||
|
LOGD("Projectile %d: pos {%.02f, %.02f, %.02f}, hit solid block at face %d",
|
||||||
|
m_UniqueID,
|
||||||
|
GetPosX(), GetPosY(), GetPosZ(),
|
||||||
|
a_BlockFace
|
||||||
|
);
|
||||||
|
|
||||||
|
m_IsInGround = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
AString cProjectileEntity::GetMCAClassName(void) const
|
||||||
|
{
|
||||||
|
switch (m_ProjectileKind)
|
||||||
|
{
|
||||||
|
case pkArrow: return "Arrow";
|
||||||
|
case pkSnowball: return "Snowball";
|
||||||
|
case pkEgg: return "Egg";
|
||||||
|
case pkGhastFireball: return "Fireball";
|
||||||
|
case pkFireCharge: return "SmallFireball";
|
||||||
|
case pkEnderPearl: return "ThrownEnderPearl";
|
||||||
|
case pkExpBottle: return "ThrownExpBottle";
|
||||||
|
case pkSplashPotion: return "ThrownPotion";
|
||||||
|
case pkWitherSkull: return "WitherSkull";
|
||||||
|
case pkFishingFloat: return ""; // Unknown, perhaps MC doesn't save this?
|
||||||
|
}
|
||||||
|
ASSERT(!"Unhandled projectile entity kind!");
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cProjectileEntity::Tick(float a_Dt, cChunk & a_Chunk)
|
||||||
|
{
|
||||||
|
super::Tick(a_Dt, a_Chunk);
|
||||||
|
BroadcastMovementUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cProjectileEntity::HandlePhysics(float a_Dt, cChunk & a_Chunk)
|
||||||
|
{
|
||||||
|
if (m_IsInGround)
|
||||||
|
{
|
||||||
|
// Already-grounded projectiles don't move at all
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3d PerTickSpeed = GetSpeed() / 20;
|
||||||
|
Vector3d Pos = GetPosition();
|
||||||
|
|
||||||
|
// Trace the tick's worth of movement as a line:
|
||||||
|
Vector3d NextPos = Pos + PerTickSpeed;
|
||||||
|
cProjectileTracerCallback TracerCallback(this);
|
||||||
|
if (cLineBlockTracer::Trace(*m_World, TracerCallback, Pos, NextPos))
|
||||||
|
{
|
||||||
|
// Nothing in the way, update the position
|
||||||
|
SetPosition(NextPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add gravity effect to the vertical speed component:
|
||||||
|
SetSpeedY(GetSpeedY() + m_Gravity / 20);
|
||||||
|
|
||||||
|
// DEBUG:
|
||||||
|
LOGD("Arrow %d: pos {%.02f, %.02f, %.02f}, speed {%.02f, %.02f, %.02f}",
|
||||||
|
m_UniqueID,
|
||||||
|
GetPosX(), GetPosY(), GetPosZ(),
|
||||||
|
GetSpeedX(), GetSpeedY(), GetSpeedZ()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// cArrowEntity:
|
||||||
|
|
||||||
|
cArrowEntity::cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed) :
|
||||||
|
super(pkArrow, a_Creator, a_X, a_Y, a_Z, 0.5, 0.5),
|
||||||
|
m_PickupState(psNoPickup),
|
||||||
|
m_DamageCoeff(2)
|
||||||
|
{
|
||||||
|
SetSpeed(a_Speed);
|
||||||
|
SetMass(0.1);
|
||||||
|
LOGD("Created arrow %d with speed {%.02f, %.02f, %.02f}",
|
||||||
|
m_UniqueID, GetSpeedX(), GetSpeedY(), GetSpeedZ()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cArrowEntity::cArrowEntity(cPlayer & a_Player, double a_Force) :
|
||||||
|
super(pkArrow, &a_Player, PosFromPlayerPos(a_Player), SpeedFromPlayerLook(a_Player, a_Force), 0.5, 0.5),
|
||||||
|
m_PickupState(psInSurvivalOrCreative),
|
||||||
|
m_DamageCoeff(2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Vector3d cArrowEntity::PosFromPlayerPos(const cPlayer & a_Player)
|
||||||
|
{
|
||||||
|
Vector3d res = a_Player.GetEyePosition();
|
||||||
|
|
||||||
|
// Adjust the position to be just outside the player's bounding box:
|
||||||
|
res.x += 0.16 * cos(a_Player.GetPitch());
|
||||||
|
res.y += -0.1;
|
||||||
|
res.z += 0.16 * sin(a_Player.GetPitch());
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Vector3d cArrowEntity::SpeedFromPlayerLook(const cPlayer & a_Player, double a_Force)
|
||||||
|
{
|
||||||
|
Vector3d res = a_Player.GetLookVector();
|
||||||
|
res.Normalize();
|
||||||
|
|
||||||
|
// TODO: Add a slight random change (+-0.0075 in each direction)
|
||||||
|
|
||||||
|
return res * a_Force * 1.5 * 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cArrowEntity::CanPickup(const cPlayer & a_Player) const
|
||||||
|
{
|
||||||
|
switch (m_PickupState)
|
||||||
|
{
|
||||||
|
case psNoPickup: return false;
|
||||||
|
case psInSurvivalOrCreative: return (a_Player.IsGameModeSurvival() || a_Player.IsGameModeCreative());
|
||||||
|
case psInCreative: return a_Player.IsGameModeCreative();
|
||||||
|
}
|
||||||
|
ASSERT(!"Unhandled pickup state");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cArrowEntity::SpawnOn(cClientHandle & a_Client)
|
||||||
|
{
|
||||||
|
a_Client.SendSpawnObject(*this, pkArrow, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
// ProjectileEntity.h
|
// ProjectileEntity.h
|
||||||
|
|
||||||
// Declares the cProjectileEntity class representing the common base class for projectiles
|
// Declares the cProjectileEntity class representing the common base class for projectiles, as well as individual projectile types
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -29,8 +29,8 @@ public:
|
|||||||
pkArrow = 60,
|
pkArrow = 60,
|
||||||
pkSnowball = 61,
|
pkSnowball = 61,
|
||||||
pkEgg = 62,
|
pkEgg = 62,
|
||||||
pkGhastFireball = 63, // TODO: Unverified TypeID, check this in ProtoProxy
|
pkGhastFireball = 63,
|
||||||
pkFireCharge = 64, // TODO: Unverified TypeID, check this in ProtoProxy
|
pkFireCharge = 64,
|
||||||
pkEnderPearl = 65,
|
pkEnderPearl = 65,
|
||||||
pkExpBottle = 75,
|
pkExpBottle = 75,
|
||||||
pkSplashPotion = 73,
|
pkSplashPotion = 73,
|
||||||
@ -38,17 +38,48 @@ public:
|
|||||||
pkFishingFloat = 90,
|
pkFishingFloat = 90,
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
// tolua_end
|
||||||
|
|
||||||
|
CLASS_PROTODEF(cProjectileEntity);
|
||||||
|
|
||||||
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
|
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
|
||||||
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
|
cProjectileEntity(eKind a_Kind, cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
|
||||||
|
|
||||||
/// Called by the physics blocktracer when the entity hits a solid block, the coords and the face hit is given
|
static cProjectileEntity * Create(eKind a_Kind, cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d * a_Speed = NULL);
|
||||||
virtual void OnHitSolidBlock(double a_BlockX, double a_BlockY, double a_BlockZ, char a_BlockFace) {};
|
|
||||||
|
/// Called by the physics blocktracer when the entity hits a solid block, the block's coords and the face hit is given
|
||||||
|
virtual void OnHitSolidBlock(int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
|
||||||
|
|
||||||
|
// tolua_begin
|
||||||
|
|
||||||
|
/// Returns the kind of the projectile (fast class identification)
|
||||||
|
eKind GetProjectileKind(void) const { return m_ProjectileKind; }
|
||||||
|
|
||||||
|
/// Returns the entity who created this projectile; may be NULL
|
||||||
|
cEntity * GetCreator(void) { return m_Creator; }
|
||||||
|
|
||||||
|
/// Returns the string that is used as the entity type (class name) in MCA files
|
||||||
|
AString GetMCAClassName(void) const;
|
||||||
|
|
||||||
|
/// Returns true if the projectile has hit the ground and is stuck there
|
||||||
|
bool IsInGround(void) const { return m_IsInGround; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
eKind m_Kind;
|
eKind m_ProjectileKind;
|
||||||
|
|
||||||
/// The entity who has created this projectile; may be NULL (e. g. for dispensers)
|
/// The entity who has created this projectile; may be NULL (e. g. for dispensers)
|
||||||
cEntity * m_Creator;
|
cEntity * m_Creator;
|
||||||
|
|
||||||
|
/// True if the projectile has hit the ground and is stuck there
|
||||||
|
bool m_IsInGround;
|
||||||
|
|
||||||
|
// tolua_end
|
||||||
|
|
||||||
|
// cEntity overrides:
|
||||||
|
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||||
|
virtual void HandlePhysics(float a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
|
// tolua_begin
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
@ -58,9 +89,64 @@ protected:
|
|||||||
class cArrowEntity :
|
class cArrowEntity :
|
||||||
public cProjectileEntity
|
public cProjectileEntity
|
||||||
{
|
{
|
||||||
|
typedef cProjectileEntity super;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, double a_Width, double a_Height);
|
/// Determines when the arrow can be picked up (depending on player gamemode). Corresponds to the MCA file "pickup" field
|
||||||
cArrowEntity(cEntity * a_Creator, const Vector3d & a_Pos, const Vector3d & a_Speed, double a_Width, double a_Height);
|
enum ePickupState
|
||||||
|
{
|
||||||
|
psNoPickup = 0,
|
||||||
|
psInSurvivalOrCreative = 1,
|
||||||
|
psInCreative = 2,
|
||||||
|
} ;
|
||||||
|
|
||||||
|
// tolua_end
|
||||||
|
|
||||||
|
CLASS_PROTODEF(cArrowEntity);
|
||||||
|
|
||||||
|
/// Creates a new arrow with psNoPickup state and default damage modifier coeff
|
||||||
|
cArrowEntity(cEntity * a_Creator, double a_X, double a_Y, double a_Z, const Vector3d a_Speed);
|
||||||
|
|
||||||
|
/// Creates a new arrow as shot by a player, initializes it from the player object
|
||||||
|
cArrowEntity(cPlayer & a_Player, double a_Force);
|
||||||
|
|
||||||
|
// tolua_begin
|
||||||
|
|
||||||
|
/// Returns the initial arrow position, as defined by the player eye position + adjustment.
|
||||||
|
static Vector3d PosFromPlayerPos(const cPlayer & a_Player);
|
||||||
|
|
||||||
|
/// Returns the initial arrow speed, as defined by the player look vector and the force coefficient
|
||||||
|
static Vector3d SpeedFromPlayerLook(const cPlayer & a_Player, double a_Force);
|
||||||
|
|
||||||
|
/// Returns whether the arrow can be picked up by players
|
||||||
|
ePickupState GetPickupState(void) const { return m_PickupState; }
|
||||||
|
|
||||||
|
/// Sets a new pickup state
|
||||||
|
void SetPickupState(ePickupState a_PickupState) { m_PickupState = a_PickupState; }
|
||||||
|
|
||||||
|
/// Returns the damage modifier coeff.
|
||||||
|
double GetDamageCoeff(void) const { return m_DamageCoeff; }
|
||||||
|
|
||||||
|
/// Sets the damage modifier coeff
|
||||||
|
void SetDamageCoeff(double a_DamageCoeff) { m_DamageCoeff = a_DamageCoeff; }
|
||||||
|
|
||||||
|
/// Returns true if the specified player can pick the arrow up
|
||||||
|
bool CanPickup(const cPlayer & a_Player) const;
|
||||||
|
|
||||||
|
// tolua_end
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/// Determines when the arrow can be picked up by players
|
||||||
|
ePickupState m_PickupState;
|
||||||
|
|
||||||
|
/// The coefficient applied to the damage that the arrow will deal, based on the bow enchantment. 2.0 for normal arrow
|
||||||
|
double m_DamageCoeff;
|
||||||
|
|
||||||
|
// cEntity overrides:
|
||||||
|
virtual void SpawnOn(cClientHandle & a_Client) override;
|
||||||
|
|
||||||
|
// tolua_begin
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
// tolua_end
|
// tolua_end
|
||||||
|
@ -29,20 +29,6 @@ cTNTEntity::cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec) :
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cTNTEntity::Initialize(cWorld * a_World)
|
|
||||||
{
|
|
||||||
if (super::Initialize(a_World))
|
|
||||||
{
|
|
||||||
a_World->BroadcastSpawnEntity(*this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle)
|
void cTNTEntity::SpawnOn(cClientHandle & a_ClientHandle)
|
||||||
{
|
{
|
||||||
a_ClientHandle.SendSpawnObject(*this, 50, 1, 0, 0); // 50 means TNT
|
a_ClientHandle.SendSpawnObject(*this, 50, 1, 0, 0); // 50 means TNT
|
||||||
|
@ -19,7 +19,6 @@ public:
|
|||||||
cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec);
|
cTNTEntity(const Vector3d & a_Pos, double a_FuseTimeInSec);
|
||||||
|
|
||||||
// cEntity overrides:
|
// cEntity overrides:
|
||||||
virtual bool Initialize(cWorld * a_World) override;
|
|
||||||
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
virtual void SpawnOn(cClientHandle & a_ClientHandle) override;
|
||||||
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(float a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
|
80
source/Items/ItemBow.h
Normal file
80
source/Items/ItemBow.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
|
||||||
|
// ItemBow.h
|
||||||
|
|
||||||
|
// Declares the cItemBowHandler class representing the itemhandler for bows
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../Entities/ProjectileEntity.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cItemBowHandler :
|
||||||
|
public cItemHandler
|
||||||
|
{
|
||||||
|
typedef cItemHandler super;
|
||||||
|
|
||||||
|
public:
|
||||||
|
cItemBowHandler(void) :
|
||||||
|
super(E_ITEM_BOW)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual bool OnItemUse(cWorld * a_World, cPlayer * a_Player, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir) override
|
||||||
|
{
|
||||||
|
ASSERT(a_Player != NULL);
|
||||||
|
|
||||||
|
// Check if the player has an arrow in the inventory, or is in Creative:
|
||||||
|
if (!(a_Player->IsGameModeCreative() || a_Player->GetInventory().HasItems(cItem(E_ITEM_ARROW))))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
a_Player->StartChargingBow();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void OnItemShoot(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) override
|
||||||
|
{
|
||||||
|
// Actual shot - produce the arrow with speed based on the ticks that the bow was charged
|
||||||
|
ASSERT(a_Player != NULL);
|
||||||
|
|
||||||
|
int BowCharge = a_Player->FinishChargingBow();
|
||||||
|
double Force = (double)BowCharge / 20;
|
||||||
|
Force = (Force * Force + 2 * Force) / 3; // This formula is used by the 1.6.2 client
|
||||||
|
if (Force < 0.1)
|
||||||
|
{
|
||||||
|
// Too little force, ignore the shot
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Force > 1)
|
||||||
|
{
|
||||||
|
Force = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the arrow entity:
|
||||||
|
cArrowEntity * Arrow = new cArrowEntity(*a_Player, Force * 2);
|
||||||
|
if (Arrow == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Arrow->Initialize(a_Player->GetWorld()))
|
||||||
|
{
|
||||||
|
delete Arrow;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
a_Player->GetWorld()->BroadcastSpawnEntity(*Arrow);
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
// Handlers:
|
// Handlers:
|
||||||
#include "ItemBed.h"
|
#include "ItemBed.h"
|
||||||
|
#include "ItemBow.h"
|
||||||
#include "ItemBrewingStand.h"
|
#include "ItemBrewingStand.h"
|
||||||
#include "ItemBucket.h"
|
#include "ItemBucket.h"
|
||||||
#include "ItemCauldron.h"
|
#include "ItemCauldron.h"
|
||||||
@ -47,18 +48,24 @@ cItemHandler * cItemHandler::m_ItemHandler[2268];
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
cItemHandler *cItemHandler::GetItemHandler(int a_ItemType)
|
cItemHandler * cItemHandler::GetItemHandler(int a_ItemType)
|
||||||
{
|
{
|
||||||
if(a_ItemType < 0) a_ItemType = 0;
|
if (a_ItemType < 0)
|
||||||
|
{
|
||||||
|
ASSERT(!"Bad item type");
|
||||||
|
a_ItemType = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if(!m_HandlerInitialized)
|
if (!m_HandlerInitialized)
|
||||||
{ //We have to initialize
|
{
|
||||||
|
// We need to initialize
|
||||||
memset(m_ItemHandler, 0, sizeof(m_ItemHandler));
|
memset(m_ItemHandler, 0, sizeof(m_ItemHandler));
|
||||||
m_HandlerInitialized = true;
|
m_HandlerInitialized = true;
|
||||||
}
|
}
|
||||||
if(m_ItemHandler[a_ItemType])
|
if (m_ItemHandler[a_ItemType] == NULL)
|
||||||
return m_ItemHandler[a_ItemType];
|
{
|
||||||
m_ItemHandler[a_ItemType] = CreateItemHandler(a_ItemType);
|
m_ItemHandler[a_ItemType] = CreateItemHandler(a_ItemType);
|
||||||
|
}
|
||||||
return m_ItemHandler[a_ItemType];
|
return m_ItemHandler[a_ItemType];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,6 +84,7 @@ cItemHandler *cItemHandler::CreateItemHandler(int a_ItemType)
|
|||||||
case E_BLOCK_SAPLING: return new cItemSaplingHandler(a_ItemType);
|
case E_BLOCK_SAPLING: return new cItemSaplingHandler(a_ItemType);
|
||||||
case E_BLOCK_WOOL: return new cItemClothHandler(a_ItemType);
|
case E_BLOCK_WOOL: return new cItemClothHandler(a_ItemType);
|
||||||
case E_ITEM_BED: return new cItemBedHandler(a_ItemType);
|
case E_ITEM_BED: return new cItemBedHandler(a_ItemType);
|
||||||
|
case E_ITEM_BOW: return new cItemBowHandler;
|
||||||
case E_ITEM_BREWING_STAND: return new cItemBrewingStandHandler(a_ItemType);
|
case E_ITEM_BREWING_STAND: return new cItemBrewingStandHandler(a_ItemType);
|
||||||
case E_ITEM_CAULDRON: return new cItemCauldronHandler(a_ItemType);
|
case E_ITEM_CAULDRON: return new cItemCauldronHandler(a_ItemType);
|
||||||
case E_ITEM_DYE: return new cItemDyeHandler(a_ItemType);
|
case E_ITEM_DYE: return new cItemDyeHandler(a_ItemType);
|
||||||
|
@ -21,8 +21,11 @@ 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 (right mouse button). Return false to make the item unusable. DEFAULT: False
|
||||||
virtual bool OnItemUse(cWorld *a_World, cPlayer *a_Player, const 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, const cItem & a_Item, int a_BlockX, int a_BlockY, int a_BlockZ, char a_Dir);
|
||||||
|
|
||||||
|
/// Called when the client sends the SHOOT status in the lclk packet
|
||||||
|
virtual void OnItemShoot(cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace) {}
|
||||||
|
|
||||||
/// 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, const cItem & a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
|
virtual bool OnDiggingBlock(cWorld * a_World, cPlayer * a_Player, const cItem & a_HeldItem, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace);
|
||||||
@ -88,7 +91,7 @@ protected:
|
|||||||
int m_ItemType;
|
int m_ItemType;
|
||||||
static cItemHandler *CreateItemHandler(int m_ItemType);
|
static cItemHandler *CreateItemHandler(int m_ItemType);
|
||||||
|
|
||||||
static cItemHandler *m_ItemHandler[2268];
|
static cItemHandler * m_ItemHandler[E_ITEM_LAST + 1];
|
||||||
static bool m_HandlerInitialized; //used to detect if the itemhandlers are initialized
|
static bool m_HandlerInitialized; //used to detect if the itemhandlers are initialized
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ bool cLineBlockTracer::Trace(double a_StartX, double a_StartY, double a_StartZ,
|
|||||||
m_DirX = (m_StartX < m_EndX) ? 1 : -1;
|
m_DirX = (m_StartX < m_EndX) ? 1 : -1;
|
||||||
m_DirY = (m_StartY < m_EndY) ? 1 : -1;
|
m_DirY = (m_StartY < m_EndY) ? 1 : -1;
|
||||||
m_DirZ = (m_StartZ < m_EndZ) ? 1 : -1;
|
m_DirZ = (m_StartZ < m_EndZ) ? 1 : -1;
|
||||||
|
m_CurrentFace = BLOCK_FACE_NONE;
|
||||||
|
|
||||||
// Check the start coords, adjust into the world:
|
// Check the start coords, adjust into the world:
|
||||||
if (m_StartY < 0)
|
if (m_StartY < 0)
|
||||||
@ -178,9 +179,9 @@ bool cLineBlockTracer::MoveToNextBlock(void)
|
|||||||
// Based on the wall hit, adjust the current coords
|
// Based on the wall hit, adjust the current coords
|
||||||
switch (Direction)
|
switch (Direction)
|
||||||
{
|
{
|
||||||
case dirX: m_CurrentX += m_DirX; break;
|
case dirX: m_CurrentX += m_DirX; m_CurrentFace = (m_DirX > 0) ? BLOCK_FACE_EAST : BLOCK_FACE_WEST; break;
|
||||||
case dirY: m_CurrentY += m_DirY; break;
|
case dirY: m_CurrentY += m_DirY; m_CurrentFace = (m_DirY > 0) ? BLOCK_FACE_BOTTOM : BLOCK_FACE_TOP; break;
|
||||||
case dirZ: m_CurrentZ += m_DirZ; break;
|
case dirZ: m_CurrentZ += m_DirZ; m_CurrentFace = (m_DirZ > 0) ? BLOCK_FACE_SOUTH : BLOCK_FACE_NORTH; break;
|
||||||
case dirNONE: return false;
|
case dirNONE: return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -211,7 +212,7 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk)
|
|||||||
int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width;
|
int RelX = m_CurrentX - a_Chunk->GetPosX() * cChunkDef::Width;
|
||||||
int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width;
|
int RelZ = m_CurrentZ - a_Chunk->GetPosZ() * cChunkDef::Width;
|
||||||
a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta);
|
a_Chunk->GetBlockTypeMeta(RelX, m_CurrentY, RelZ, BlockType, BlockMeta);
|
||||||
if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta))
|
if (m_Callbacks->OnNextBlock(m_CurrentX, m_CurrentY, m_CurrentZ, BlockType, BlockMeta, m_CurrentFace))
|
||||||
{
|
{
|
||||||
// The callback terminated the trace
|
// The callback terminated the trace
|
||||||
return false;
|
return false;
|
||||||
@ -219,7 +220,7 @@ bool cLineBlockTracer::Item(cChunk * a_Chunk)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ))
|
if (m_Callbacks->OnNextBlockNoData(m_CurrentX, m_CurrentY, m_CurrentZ, m_CurrentFace))
|
||||||
{
|
{
|
||||||
// The callback terminated the trace
|
// The callback terminated the trace
|
||||||
return false;
|
return false;
|
||||||
|
@ -61,6 +61,9 @@ protected:
|
|||||||
// The current block
|
// The current block
|
||||||
int m_CurrentX, m_CurrentY, m_CurrentZ;
|
int m_CurrentX, m_CurrentY, m_CurrentZ;
|
||||||
|
|
||||||
|
// The face through which the current block has been entered
|
||||||
|
char m_CurrentFace;
|
||||||
|
|
||||||
|
|
||||||
/// Adjusts the start point above the world to just at the world's top
|
/// Adjusts the start point above the world to just at the world's top
|
||||||
void FixStartAboveWorld(void);
|
void FixStartAboveWorld(void);
|
||||||
|
@ -1649,7 +1649,7 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
|
virtual bool OnNextBlock(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta, char a_EntryFace) override
|
||||||
{
|
{
|
||||||
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlock"))
|
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlock"))
|
||||||
{
|
{
|
||||||
@ -1661,6 +1661,7 @@ public:
|
|||||||
m_LuaState.Push(a_BlockZ);
|
m_LuaState.Push(a_BlockZ);
|
||||||
m_LuaState.Push(a_BlockType);
|
m_LuaState.Push(a_BlockType);
|
||||||
m_LuaState.Push(a_BlockMeta);
|
m_LuaState.Push(a_BlockMeta);
|
||||||
|
m_LuaState.Push(a_EntryFace);
|
||||||
if (!m_LuaState.CallFunction(1))
|
if (!m_LuaState.CallFunction(1))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -1674,7 +1675,7 @@ public:
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ) override
|
virtual bool OnNextBlockNoData(int a_BlockX, int a_BlockY, int a_BlockZ, char a_EntryFace) override
|
||||||
{
|
{
|
||||||
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlockNoData"))
|
if (!m_LuaState.PushFunctionFromRefTable(m_TableRef, "OnNextBlockNoData"))
|
||||||
{
|
{
|
||||||
@ -1684,6 +1685,7 @@ public:
|
|||||||
m_LuaState.Push(a_BlockX);
|
m_LuaState.Push(a_BlockX);
|
||||||
m_LuaState.Push(a_BlockY);
|
m_LuaState.Push(a_BlockY);
|
||||||
m_LuaState.Push(a_BlockZ);
|
m_LuaState.Push(a_BlockZ);
|
||||||
|
m_LuaState.Push(a_EntryFace);
|
||||||
if (!m_LuaState.CallFunction(1))
|
if (!m_LuaState.CallFunction(1))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -30,12 +30,13 @@ public: // tolua_export
|
|||||||
void operator -= ( Vector3d* a_V ) { x -= a_V->x; y -= a_V->y; z -= a_V->z; }
|
void operator -= ( Vector3d* a_V ) { x -= a_V->x; y -= a_V->y; z -= a_V->z; }
|
||||||
void operator *= ( double a_f ) { x *= a_f; y *= a_f; z *= a_f; }
|
void operator *= ( double a_f ) { x *= a_f; y *= a_f; z *= a_f; }
|
||||||
|
|
||||||
Vector3d operator + ( const Vector3d& v2 ) const { return Vector3d( x + v2.x, y + v2.y, z + v2.z ); } // tolua_export
|
Vector3d operator + (const Vector3d & v2) const { return Vector3d(x + v2.x, y + v2.y, z + v2.z ); } // tolua_export
|
||||||
Vector3d operator + ( const Vector3d* v2 ) const { return Vector3d( x + v2->x, y + v2->y, z + v2->z ); } // tolua_export
|
Vector3d operator + (const Vector3d * v2) const { return Vector3d(x + v2->x, y + v2->y, z + v2->z ); } // tolua_export
|
||||||
Vector3d operator - ( const Vector3d& v2 ) const { return Vector3d( x - v2.x, y - v2.y, z - v2.z ); } // tolua_export
|
Vector3d operator - (const Vector3d & v2) const { return Vector3d(x - v2.x, y - v2.y, z - v2.z ); } // tolua_export
|
||||||
Vector3d operator - ( const Vector3d* v2 ) const { return Vector3d( x - v2->x, y - v2->y, z - v2->z ); } // tolua_export
|
Vector3d operator - (const Vector3d * v2) const { return Vector3d(x - v2->x, y - v2->y, z - v2->z ); } // tolua_export
|
||||||
Vector3d operator * ( const double f ) const { return Vector3d( x * f, y * f, z * f ); } // tolua_export
|
Vector3d operator * (const double f) const { return Vector3d(x * f, y * f, z * f ); } // tolua_export
|
||||||
Vector3d operator * ( const Vector3d& v2 ) const { return Vector3d( x * v2.x, y * v2.y, z * v2.z ); } // tolua_export
|
Vector3d operator * (const Vector3d & v2) const { return Vector3d(x * v2.x, y * v2.y, z * v2.z ); } // tolua_export
|
||||||
|
Vector3d operator / (const double f) const { return Vector3d(x / f, y / f, z / f ); } // tolua_export
|
||||||
|
|
||||||
double x, y, z; // tolua_export
|
double x, y, z; // tolua_export
|
||||||
|
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
#include "World.h"
|
#include "World.h"
|
||||||
#include "ChunkDef.h"
|
#include "ChunkDef.h"
|
||||||
#include "ClientHandle.h"
|
#include "ClientHandle.h"
|
||||||
#include "Entities/Pickup.h"
|
|
||||||
#include "Entities/Player.h"
|
|
||||||
#include "Server.h"
|
#include "Server.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
#include "Root.h"
|
#include "Root.h"
|
||||||
@ -14,6 +12,11 @@
|
|||||||
#include "ChunkMap.h"
|
#include "ChunkMap.h"
|
||||||
#include "OSSupport/Timer.h"
|
#include "OSSupport/Timer.h"
|
||||||
|
|
||||||
|
// Entities (except mobs):
|
||||||
|
#include "Entities/Pickup.h"
|
||||||
|
#include "Entities/Player.h"
|
||||||
|
#include "Entities/TNTEntity.h"
|
||||||
|
|
||||||
// Simulators:
|
// Simulators:
|
||||||
#include "Simulator/SimulatorManager.h"
|
#include "Simulator/SimulatorManager.h"
|
||||||
#include "Simulator/FloodyFluidSimulator.h"
|
#include "Simulator/FloodyFluidSimulator.h"
|
||||||
@ -55,7 +58,6 @@
|
|||||||
#include "PluginManager.h"
|
#include "PluginManager.h"
|
||||||
#include "Blocks/BlockHandler.h"
|
#include "Blocks/BlockHandler.h"
|
||||||
#include "Vector3d.h"
|
#include "Vector3d.h"
|
||||||
#include "Entities/TNTEntity.h"
|
|
||||||
|
|
||||||
#include "Tracer.h"
|
#include "Tracer.h"
|
||||||
#include "tolua++.h"
|
#include "tolua++.h"
|
||||||
@ -2647,6 +2649,26 @@ int cWorld::SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eTyp
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int cWorld::CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const Vector3d * a_Speed)
|
||||||
|
{
|
||||||
|
cProjectileEntity * Projectile = cProjectileEntity::Create(a_Kind, a_Creator, a_PosX, a_PosY, a_PosZ, a_Speed);
|
||||||
|
if (Projectile == NULL)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!Projectile->Initialize(this))
|
||||||
|
{
|
||||||
|
delete Projectile;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
BroadcastSpawnEntity(*Projectile);
|
||||||
|
return Projectile->GetUniqueID();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cWorld::TabCompleteUserName(const AString & a_Text, AStringVector & a_Results)
|
void cWorld::TabCompleteUserName(const AString & a_Text, AStringVector & a_Results)
|
||||||
{
|
{
|
||||||
cCSLock Lock(m_CSPlayers);
|
cCSLock Lock(m_CSPlayers);
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "LightingThread.h"
|
#include "LightingThread.h"
|
||||||
#include "Item.h"
|
#include "Item.h"
|
||||||
#include "Mobs/Monster.h"
|
#include "Mobs/Monster.h"
|
||||||
|
#include "Entities/ProjectileEntity.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -573,6 +574,9 @@ public:
|
|||||||
/// Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise
|
/// Spawns a mob of the specified type. Returns the mob's EntityID if recognized and spawned, <0 otherwise
|
||||||
int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType); // tolua_export
|
int SpawnMob(double a_PosX, double a_PosY, double a_PosZ, cMonster::eType a_MonsterType); // tolua_export
|
||||||
|
|
||||||
|
/// Creates a projectile of the specified type. Returns the projectile's EntityID if successful, <0 otherwise
|
||||||
|
int CreateProjectile(double a_PosX, double a_PosY, double a_PosZ, cProjectileEntity::eKind a_Kind, cEntity * a_Creator, const Vector3d * a_Speed = NULL); // tolua_export
|
||||||
|
|
||||||
/// Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread!
|
/// Returns a random number from the m_TickRand in range [0 .. a_Range]. To be used only in the tick thread!
|
||||||
int GetTickRandomNumber(unsigned a_Range) { return (int)(m_TickRand.randInt(a_Range)); }
|
int GetTickRandomNumber(unsigned a_Range) { return (int)(m_TickRand.randInt(a_Range)); }
|
||||||
|
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include "../Entities/Minecart.h"
|
#include "../Entities/Minecart.h"
|
||||||
#include "../Mobs/Monster.h"
|
#include "../Mobs/Monster.h"
|
||||||
#include "../Entities/Pickup.h"
|
#include "../Entities/Pickup.h"
|
||||||
|
#include "../Entities/ProjectileEntity.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -330,6 +332,62 @@ void cNBTChunkSerializer::AddPickupEntity(cPickup * a_Pickup)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cNBTChunkSerializer::AddProjectileEntity(cProjectileEntity * a_Projectile)
|
||||||
|
{
|
||||||
|
m_Writer.BeginCompound("");
|
||||||
|
AddBasicEntity(a_Projectile, a_Projectile->GetMCAClassName());
|
||||||
|
Vector3d Pos = a_Projectile->GetPosition();
|
||||||
|
m_Writer.AddShort("xTile", (Int16)floor(Pos.x));
|
||||||
|
m_Writer.AddShort("yTile", (Int16)floor(Pos.y));
|
||||||
|
m_Writer.AddShort("zTile", (Int16)floor(Pos.z));
|
||||||
|
m_Writer.AddShort("inTile", 0); // TODO: Query the block type (is it needed?)
|
||||||
|
m_Writer.AddShort("shake", 0); // TODO: Any shake?
|
||||||
|
m_Writer.AddByte ("inGround", a_Projectile->IsInGround() ? 1 : 0);
|
||||||
|
|
||||||
|
switch (a_Projectile->GetProjectileKind())
|
||||||
|
{
|
||||||
|
case cProjectileEntity::pkArrow:
|
||||||
|
{
|
||||||
|
m_Writer.AddByte("inData", 0); // TODO: Query the block meta (is it needed?)
|
||||||
|
m_Writer.AddByte("pickup", ((cArrowEntity *)a_Projectile)->GetPickupState());
|
||||||
|
m_Writer.AddDouble("damage", ((cArrowEntity *)a_Projectile)->GetDamageCoeff());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case cProjectileEntity::pkGhastFireball:
|
||||||
|
{
|
||||||
|
m_Writer.AddInt("ExplosionPower", 1);
|
||||||
|
// fall-through:
|
||||||
|
}
|
||||||
|
case cProjectileEntity::pkFireCharge:
|
||||||
|
case cProjectileEntity::pkWitherSkull:
|
||||||
|
{
|
||||||
|
m_Writer.BeginList("Motion", TAG_Double);
|
||||||
|
m_Writer.AddDouble("", a_Projectile->GetSpeedX());
|
||||||
|
m_Writer.AddDouble("", a_Projectile->GetSpeedY());
|
||||||
|
m_Writer.AddDouble("", a_Projectile->GetSpeedZ());
|
||||||
|
m_Writer.EndList();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
ASSERT(!"Unsaved projectile entity!");
|
||||||
|
}
|
||||||
|
} // switch (ProjectileKind)
|
||||||
|
cEntity * Creator = a_Projectile->GetCreator();
|
||||||
|
if (Creator != NULL)
|
||||||
|
{
|
||||||
|
if (Creator->GetEntityType() == cEntity::etPlayer)
|
||||||
|
{
|
||||||
|
m_Writer.AddString("ownerName", ((cPlayer *)Creator)->GetName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_Writer.EndCompound();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Minecart)
|
void cNBTChunkSerializer::AddMinecartChestContents(cMinecartWithChest * a_Minecart)
|
||||||
{
|
{
|
||||||
m_Writer.BeginList("Items", TAG_Compound);
|
m_Writer.BeginList("Items", TAG_Compound);
|
||||||
@ -403,10 +461,11 @@ void cNBTChunkSerializer::Entity(cEntity * a_Entity)
|
|||||||
|
|
||||||
switch (a_Entity->GetEntityType())
|
switch (a_Entity->GetEntityType())
|
||||||
{
|
{
|
||||||
case cEntity::etFallingBlock: AddFallingBlockEntity((cFallingBlock *)a_Entity); break;
|
case cEntity::etFallingBlock: AddFallingBlockEntity((cFallingBlock *) a_Entity); break;
|
||||||
case cEntity::etMinecart: AddMinecartEntity ((cMinecart *) a_Entity); break;
|
case cEntity::etMinecart: AddMinecartEntity ((cMinecart *) a_Entity); break;
|
||||||
case cEntity::etMonster: AddMonsterEntity ((cMonster *) a_Entity); break;
|
case cEntity::etMonster: AddMonsterEntity ((cMonster *) a_Entity); break;
|
||||||
case cEntity::etPickup: AddPickupEntity ((cPickup *) a_Entity); break;
|
case cEntity::etPickup: AddPickupEntity ((cPickup *) a_Entity); break;
|
||||||
|
case cEntity::etProjectile: AddProjectileEntity ((cProjectileEntity *)a_Entity); break;
|
||||||
case cEntity::etPlayer: return; // Players aren't saved into the world
|
case cEntity::etPlayer: return; // Players aren't saved into the world
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,7 @@ class cMinecartWithHopper;
|
|||||||
class cMonster;
|
class cMonster;
|
||||||
class cPickup;
|
class cPickup;
|
||||||
class cItemGrid;
|
class cItemGrid;
|
||||||
|
class cProjectileEntity;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -97,6 +98,7 @@ protected:
|
|||||||
void AddMinecartEntity (cMinecart * a_Minecart);
|
void AddMinecartEntity (cMinecart * a_Minecart);
|
||||||
void AddMonsterEntity (cMonster * a_Monster);
|
void AddMonsterEntity (cMonster * a_Monster);
|
||||||
void AddPickupEntity (cPickup * a_Pickup);
|
void AddPickupEntity (cPickup * a_Pickup);
|
||||||
|
void AddProjectileEntity (cProjectileEntity * a_Projectile);
|
||||||
|
|
||||||
void AddMinecartChestContents(cMinecartWithChest * a_Minecart);
|
void AddMinecartChestContents(cMinecartWithChest * a_Minecart);
|
||||||
|
|
||||||
|
@ -20,13 +20,13 @@
|
|||||||
#include "../Item.h"
|
#include "../Item.h"
|
||||||
#include "../ItemGrid.h"
|
#include "../ItemGrid.h"
|
||||||
#include "../StringCompression.h"
|
#include "../StringCompression.h"
|
||||||
#include "../Entities/Entity.h"
|
|
||||||
#include "../OSSupport/MakeDir.h"
|
#include "../OSSupport/MakeDir.h"
|
||||||
#include "FastNBT.h"
|
#include "FastNBT.h"
|
||||||
|
#include "../Mobs/Monster.h"
|
||||||
#include "../Entities/FallingBlock.h"
|
#include "../Entities/FallingBlock.h"
|
||||||
#include "../Entities/Minecart.h"
|
#include "../Entities/Minecart.h"
|
||||||
#include "../Mobs/Monster.h"
|
|
||||||
#include "../Entities/Pickup.h"
|
#include "../Entities/Pickup.h"
|
||||||
|
#include "../Entities/ProjectileEntity.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -956,6 +956,10 @@ void cWSSAnvil::LoadEntityFromNBT(cEntityList & a_Entities, const cParsedNBT & a
|
|||||||
{
|
{
|
||||||
LoadPickupFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
LoadPickupFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||||
}
|
}
|
||||||
|
if (strncmp(a_IDTag, "Arrow", a_IDTagLength) == 0)
|
||||||
|
{
|
||||||
|
LoadArrowFromNBT(a_Entities, a_NBT, a_EntityTagIdx);
|
||||||
|
}
|
||||||
// TODO: other entities
|
// TODO: other entities
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1043,7 +1047,7 @@ void cWSSAnvil::LoadMinecartTFromNBT(cEntityList & a_Entities, const cParsedNBT
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Everything to do with TNT carts
|
// TODO: Everything to do with TNT carts
|
||||||
|
|
||||||
a_Entities.push_back(Minecart.release());
|
a_Entities.push_back(Minecart.release());
|
||||||
}
|
}
|
||||||
@ -1060,7 +1064,7 @@ void cWSSAnvil::LoadMinecartHFromNBT(cEntityList & a_Entities, const cParsedNBT
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Everything to do with hopper carts
|
// TODO: Everything to do with hopper carts
|
||||||
|
|
||||||
a_Entities.push_back(Minecart.release());
|
a_Entities.push_back(Minecart.release());
|
||||||
}
|
}
|
||||||
@ -1093,6 +1097,45 @@ void cWSSAnvil::LoadPickupFromNBT(cEntityList & a_Entities, const cParsedNBT & a
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cWSSAnvil::LoadArrowFromNBT(cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||||
|
{
|
||||||
|
std::auto_ptr<cArrowEntity> Arrow(new cArrowEntity(NULL, 0, 0, 0, Vector3d(0, 0, 0)));
|
||||||
|
if (!LoadEntityBaseFromNBT(*Arrow.get(), a_NBT, a_TagIdx))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load pickup state:
|
||||||
|
int PickupIdx = a_NBT.FindChildByName(a_TagIdx, "pickup");
|
||||||
|
if (PickupIdx > 0)
|
||||||
|
{
|
||||||
|
Arrow->SetPickupState((cArrowEntity::ePickupState)a_NBT.GetByte(PickupIdx));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Try the older "player" tag:
|
||||||
|
int PlayerIdx = a_NBT.FindChildByName(a_TagIdx, "player");
|
||||||
|
if (PlayerIdx > 0)
|
||||||
|
{
|
||||||
|
Arrow->SetPickupState((a_NBT.GetByte(PlayerIdx) == 0) ? cArrowEntity::psNoPickup : cArrowEntity::psInSurvivalOrCreative);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load damage:
|
||||||
|
int DamageIdx = a_NBT.FindChildByName(a_TagIdx, "damage");
|
||||||
|
if (DamageIdx > 0)
|
||||||
|
{
|
||||||
|
Arrow->SetDamageCoeff(a_NBT.GetDouble(DamageIdx));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the new arrow in the entities list:
|
||||||
|
a_Entities.push_back(Arrow.release());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
|
bool cWSSAnvil::LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx)
|
||||||
{
|
{
|
||||||
double Pos[3];
|
double Pos[3];
|
||||||
|
@ -145,6 +145,7 @@ protected:
|
|||||||
void LoadMinecartTFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
void LoadMinecartTFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||||
void LoadMinecartHFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
void LoadMinecartHFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||||
void LoadPickupFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
void LoadPickupFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||||
|
void LoadArrowFromNBT (cEntityList & a_Entities, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||||
|
|
||||||
/// Loads entity common data from the NBT compound; returns true if successful
|
/// Loads entity common data from the NBT compound; returns true if successful
|
||||||
bool LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx);
|
bool LoadEntityBaseFromNBT(cEntity & a_Entity, const cParsedNBT & a_NBT, int a_TagIdx);
|
||||||
|
Loading…
Reference in New Issue
Block a user