1
0
cuberite-2a/src/Items/ItemBoat.h
x12xx12x 3ff57559e3
ItemHandler initialisation is a constant expression (#5344)
* Transition to non-pointer item handler
* That is my destructor - I decide when I leave this world
* I declare your destruction private and you final
2021-12-01 23:31:10 +00:00

98 lines
2.1 KiB
C++

#pragma once
#include "../Entities/Boat.h"
#include "../LineBlockTracer.h"
class cItemBoatHandler final:
public cItemHandler
{
using Super = cItemHandler;
public:
using Super::Super;
virtual bool OnItemUse(
cWorld * a_World,
cPlayer * a_Player,
cBlockPluginInterface & a_PluginInterface,
const cItem & a_HeldItem,
const Vector3i a_ClickedBlockPos,
eBlockFace a_ClickedBlockFace
) const override
{
// Only allow placing blocks on top of blocks, or when not in range of dest block:
if ((a_ClickedBlockFace != BLOCK_FACE_YM) && (a_ClickedBlockFace != BLOCK_FACE_NONE))
{
return false;
}
// Find the actual placement position by tracing line of sight until non-air block:
class cCallbacks:
public cBlockTracer::cCallbacks
{
public:
Vector3d m_Pos;
bool m_HasFound;
cCallbacks():
m_HasFound(false)
{
}
virtual bool OnNextBlock(Vector3i a_CBBlockPos, BLOCKTYPE a_CBBlockType, NIBBLETYPE a_CBBlockMeta, eBlockFace a_CBEntryFace) override
{
if (a_CBBlockType != E_BLOCK_AIR)
{
m_Pos = a_CBBlockPos;
m_HasFound = true;
return true;
}
return false;
}
} Callbacks;
auto Start = a_Player->GetEyePosition() + a_Player->GetLookVector();
auto End = a_Player->GetEyePosition() + a_Player->GetLookVector() * 5;
cLineBlockTracer::Trace(*a_World, Callbacks, Start, End);
if (!Callbacks.m_HasFound)
{
return false;
}
// Block above must be air to spawn a boat (prevents spawning a boat underwater)
auto PosAbove = Callbacks.m_Pos.Floor().addedY(1);
if (!cChunkDef::IsValidHeight(PosAbove.y))
{
return false;
}
BLOCKTYPE BlockAbove = a_World->GetBlock(PosAbove);
if (BlockAbove != E_BLOCK_AIR)
{
return false;
}
// Spawn block at water level
if (a_World->SpawnBoat(Callbacks.m_Pos + Vector3d(0.5, 1, 0.5), cBoat::ItemToMaterial(a_Player->GetEquippedItem())) == cEntity::INVALID_ID)
{
return false;
}
// Remove boat from players hand
if (!a_Player->IsGameModeCreative())
{
a_Player->GetInventory().RemoveOneEquippedItem();
}
return true;
}
} ;