Check for intersection between placed blocks and entities. (#3850)
* Check for intersection between placed blocks and entities. + Implemented GetPlacementCollisionBox, to permit custom placement collision boxes for blocks. * Factored block-entity placement checking into another function in cPlayer. - Removed vector min/max functions * Use GetWorld to get the world in DoesPlacingBlocksIntersectEntity. + Added block height checks, allow different cEntity subclasses to decide whether they will prevent block placement.
This commit is contained in:
parent
eb4432bb62
commit
5402b214b3
|
@ -3059,6 +3059,16 @@ local Hash = cCryptoHash.sha1HexString("DataToHash")
|
||||||
},
|
},
|
||||||
Notes = "Schedules the entity to be destroyed; if ShouldBroadcast is not present or set to true, broadcasts the DestroyEntity packet",
|
Notes = "Schedules the entity to be destroyed; if ShouldBroadcast is not present or set to true, broadcasts the DestroyEntity packet",
|
||||||
},
|
},
|
||||||
|
DoesPreventBlockPlacement =
|
||||||
|
{
|
||||||
|
Returns =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
Type = "boolean",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Notes = "Returns true if this entity doesn't allow blocks to be placed intersecting the entity.",
|
||||||
|
},
|
||||||
GetAirLevel =
|
GetAirLevel =
|
||||||
{
|
{
|
||||||
Returns =
|
Returns =
|
||||||
|
|
|
@ -106,6 +106,16 @@ void cBlockDoorHandler::OnCancelRightClick(cChunkInterface & a_ChunkInterface, c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBoundingBox cBlockDoorHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP)
|
||||||
|
{
|
||||||
|
// Doors can be placed inside the player
|
||||||
|
return cBoundingBox(0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NIBBLETYPE cBlockDoorHandler::MetaRotateCCW(NIBBLETYPE a_Meta)
|
NIBBLETYPE cBlockDoorHandler::MetaRotateCCW(NIBBLETYPE a_Meta)
|
||||||
{
|
{
|
||||||
if (a_Meta & 0x08)
|
if (a_Meta & 0x08)
|
||||||
|
|
|
@ -52,6 +52,8 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) override;
|
||||||
|
|
||||||
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
|
||||||
{
|
{
|
||||||
if ((a_BlockMeta & 0x08) != 0) // is top part of door
|
if ((a_BlockMeta & 0x08) != 0) // is top part of door
|
||||||
|
|
80
src/Blocks/BlockFence.h
Normal file
80
src/Blocks/BlockFence.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "BlockHandler.h"
|
||||||
|
#include "BlockID.h"
|
||||||
|
#include "../BoundingBox.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class cBlockFenceHandler :
|
||||||
|
public cBlockHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// These are the min and max coordinates (X and Z) for a straight fence.
|
||||||
|
// 0.4 and 0.6 are really just guesses, but they seem pretty good.
|
||||||
|
// (0.4 to 0.6 is a fence that's 0.2 wide, down the center of the block)
|
||||||
|
const double MIN_COORD = 0.4;
|
||||||
|
const double MAX_COORD = 0.6;
|
||||||
|
|
||||||
|
cBlockFenceHandler(BLOCKTYPE a_BlockType)
|
||||||
|
: cBlockHandler(a_BlockType)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP) override
|
||||||
|
{
|
||||||
|
bool XMSolid = cBlockInfo::IsSolid(a_XM);
|
||||||
|
bool XPSolid = cBlockInfo::IsSolid(a_XP);
|
||||||
|
bool ZMSolid = cBlockInfo::IsSolid(a_ZM);
|
||||||
|
bool ZPSolid = cBlockInfo::IsSolid(a_ZP);
|
||||||
|
|
||||||
|
double FENCE_HEIGHT = cBlockInfo::GetBlockHeight(m_BlockType);
|
||||||
|
|
||||||
|
// Entities can never be in the center
|
||||||
|
cBoundingBox PlacementBox(MIN_COORD, MAX_COORD, 0, FENCE_HEIGHT, MIN_COORD, MAX_COORD);
|
||||||
|
|
||||||
|
// For each solid neighbor, the hitbox extends that way
|
||||||
|
if (XMSolid)
|
||||||
|
{
|
||||||
|
PlacementBox = PlacementBox.Union(cBoundingBox(0, 0.5, 0, FENCE_HEIGHT, MIN_COORD, MAX_COORD));
|
||||||
|
}
|
||||||
|
if (XPSolid)
|
||||||
|
{
|
||||||
|
PlacementBox = PlacementBox.Union(cBoundingBox(0.5, 1.0, 0, FENCE_HEIGHT, MIN_COORD, MAX_COORD));
|
||||||
|
}
|
||||||
|
if (ZMSolid)
|
||||||
|
{
|
||||||
|
PlacementBox = PlacementBox.Union(cBoundingBox(MIN_COORD, MAX_COORD, 0, FENCE_HEIGHT, 0.0, 0.5));
|
||||||
|
}
|
||||||
|
if (ZPSolid)
|
||||||
|
{
|
||||||
|
PlacementBox = PlacementBox.Union(cBoundingBox(MIN_COORD, MAX_COORD, 0, FENCE_HEIGHT, 0.5, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// For each corner, fill in the corner
|
||||||
|
if (XMSolid && ZMSolid)
|
||||||
|
{
|
||||||
|
PlacementBox = PlacementBox.Union(cBoundingBox(0, 0.5, 0, FENCE_HEIGHT, 0, 0.5));
|
||||||
|
}
|
||||||
|
if (XPSolid && ZMSolid)
|
||||||
|
{
|
||||||
|
PlacementBox = PlacementBox.Union(cBoundingBox(0.5, 1.0, 0, FENCE_HEIGHT, 0, 0.5));
|
||||||
|
}
|
||||||
|
if (XPSolid && ZPSolid)
|
||||||
|
{
|
||||||
|
PlacementBox = PlacementBox.Union(cBoundingBox(0.5, 1.0, 0, FENCE_HEIGHT, 0.5, 1.0));
|
||||||
|
}
|
||||||
|
if (XMSolid && ZPSolid)
|
||||||
|
{
|
||||||
|
PlacementBox = PlacementBox.Union(cBoundingBox(0, 0.5, 0, FENCE_HEIGHT, 0.5, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return PlacementBox;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "BlockEnderchest.h"
|
#include "BlockEnderchest.h"
|
||||||
#include "BlockEntity.h"
|
#include "BlockEntity.h"
|
||||||
#include "BlockFarmland.h"
|
#include "BlockFarmland.h"
|
||||||
|
#include "BlockFence.h"
|
||||||
#include "BlockFenceGate.h"
|
#include "BlockFenceGate.h"
|
||||||
#include "BlockFire.h"
|
#include "BlockFire.h"
|
||||||
#include "BlockFlower.h"
|
#include "BlockFlower.h"
|
||||||
|
@ -181,6 +182,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
// Block handlers, alphabetically sorted:
|
// Block handlers, alphabetically sorted:
|
||||||
case E_BLOCK_ACACIA_DOOR: return new cBlockDoorHandler (a_BlockType);
|
case E_BLOCK_ACACIA_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||||
|
case E_BLOCK_ACACIA_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||||
case E_BLOCK_ACACIA_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
case E_BLOCK_ACACIA_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||||
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
case E_BLOCK_ACACIA_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||||
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
|
case E_BLOCK_ACTIVATOR_RAIL: return new cBlockRailHandler (a_BlockType);
|
||||||
|
@ -190,6 +192,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
case E_BLOCK_BEETROOTS: return new cBlockCropsHandler<3> (a_BlockType); // 4 stages of growth
|
case E_BLOCK_BEETROOTS: return new cBlockCropsHandler<3> (a_BlockType); // 4 stages of growth
|
||||||
case E_BLOCK_BIG_FLOWER: return new cBlockBigFlowerHandler (a_BlockType);
|
case E_BLOCK_BIG_FLOWER: return new cBlockBigFlowerHandler (a_BlockType);
|
||||||
case E_BLOCK_BIRCH_DOOR: return new cBlockDoorHandler (a_BlockType);
|
case E_BLOCK_BIRCH_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||||
|
case E_BLOCK_BIRCH_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||||
case E_BLOCK_BIRCH_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
case E_BLOCK_BIRCH_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||||
case E_BLOCK_BIRCH_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
case E_BLOCK_BIRCH_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||||
case E_BLOCK_BREWING_STAND: return new cBlockBrewingStandHandler (a_BlockType);
|
case E_BLOCK_BREWING_STAND: return new cBlockBrewingStandHandler (a_BlockType);
|
||||||
|
@ -212,6 +215,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
case E_BLOCK_COBWEB: return new cBlockCobWebHandler (a_BlockType);
|
case E_BLOCK_COBWEB: return new cBlockCobWebHandler (a_BlockType);
|
||||||
case E_BLOCK_CROPS: return new cBlockCropsHandler<7> (a_BlockType); // 8 stages of growth
|
case E_BLOCK_CROPS: return new cBlockCropsHandler<7> (a_BlockType); // 8 stages of growth
|
||||||
case E_BLOCK_DARK_OAK_DOOR: return new cBlockDoorHandler (a_BlockType);
|
case E_BLOCK_DARK_OAK_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||||
|
case E_BLOCK_DARK_OAK_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||||
case E_BLOCK_DARK_OAK_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
case E_BLOCK_DARK_OAK_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||||
case E_BLOCK_DARK_OAK_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
case E_BLOCK_DARK_OAK_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||||
case E_BLOCK_DEAD_BUSH: return new cBlockDeadBushHandler (a_BlockType);
|
case E_BLOCK_DEAD_BUSH: return new cBlockDeadBushHandler (a_BlockType);
|
||||||
|
@ -227,6 +231,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
case E_BLOCK_ENCHANTMENT_TABLE: return new cBlockEnchantmentTableHandler(a_BlockType);
|
case E_BLOCK_ENCHANTMENT_TABLE: return new cBlockEnchantmentTableHandler(a_BlockType);
|
||||||
case E_BLOCK_ENDER_CHEST: return new cBlockEnderchestHandler (a_BlockType);
|
case E_BLOCK_ENDER_CHEST: return new cBlockEnderchestHandler (a_BlockType);
|
||||||
case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler (a_BlockType);
|
case E_BLOCK_FARMLAND: return new cBlockFarmlandHandler (a_BlockType);
|
||||||
|
case E_BLOCK_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||||
case E_BLOCK_FROSTED_ICE: return new cBlockIceHandler (a_BlockType);
|
case E_BLOCK_FROSTED_ICE: return new cBlockIceHandler (a_BlockType);
|
||||||
case E_BLOCK_FIRE: return new cBlockFireHandler (a_BlockType);
|
case E_BLOCK_FIRE: return new cBlockFireHandler (a_BlockType);
|
||||||
case E_BLOCK_FLOWER_POT: return new cBlockFlowerPotHandler (a_BlockType);
|
case E_BLOCK_FLOWER_POT: return new cBlockFlowerPotHandler (a_BlockType);
|
||||||
|
@ -249,6 +254,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
case E_BLOCK_JACK_O_LANTERN: return new cBlockPumpkinHandler (a_BlockType);
|
case E_BLOCK_JACK_O_LANTERN: return new cBlockPumpkinHandler (a_BlockType);
|
||||||
case E_BLOCK_JUKEBOX: return new cBlockEntityHandler (a_BlockType);
|
case E_BLOCK_JUKEBOX: return new cBlockEntityHandler (a_BlockType);
|
||||||
case E_BLOCK_JUNGLE_DOOR: return new cBlockDoorHandler (a_BlockType);
|
case E_BLOCK_JUNGLE_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||||
|
case E_BLOCK_JUNGLE_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||||
case E_BLOCK_JUNGLE_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
case E_BLOCK_JUNGLE_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||||
case E_BLOCK_JUNGLE_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
case E_BLOCK_JUNGLE_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||||
case E_BLOCK_LADDER: return new cBlockLadderHandler (a_BlockType);
|
case E_BLOCK_LADDER: return new cBlockLadderHandler (a_BlockType);
|
||||||
|
@ -264,6 +270,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
case E_BLOCK_MELON_STEM: return new cBlockStemsHandler (a_BlockType);
|
case E_BLOCK_MELON_STEM: return new cBlockStemsHandler (a_BlockType);
|
||||||
case E_BLOCK_MOB_SPAWNER: return new cBlockMobSpawnerHandler (a_BlockType);
|
case E_BLOCK_MOB_SPAWNER: return new cBlockMobSpawnerHandler (a_BlockType);
|
||||||
case E_BLOCK_MYCELIUM: return new cBlockMyceliumHandler (a_BlockType);
|
case E_BLOCK_MYCELIUM: return new cBlockMyceliumHandler (a_BlockType);
|
||||||
|
case E_BLOCK_NETHER_BRICK_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||||
case E_BLOCK_NETHER_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
case E_BLOCK_NETHER_BRICK_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||||
case E_BLOCK_NETHER_PORTAL: return new cBlockPortalHandler (a_BlockType);
|
case E_BLOCK_NETHER_PORTAL: return new cBlockPortalHandler (a_BlockType);
|
||||||
case E_BLOCK_NETHER_WART: return new cBlockNetherWartHandler (a_BlockType);
|
case E_BLOCK_NETHER_WART: return new cBlockNetherWartHandler (a_BlockType);
|
||||||
|
@ -308,6 +315,7 @@ cBlockHandler * cBlockHandler::CreateBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
case E_BLOCK_SNOW: return new cBlockSnowHandler (a_BlockType);
|
case E_BLOCK_SNOW: return new cBlockSnowHandler (a_BlockType);
|
||||||
case E_BLOCK_SLIME_BLOCK: return new cBlockSlimeHandler (a_BlockType);
|
case E_BLOCK_SLIME_BLOCK: return new cBlockSlimeHandler (a_BlockType);
|
||||||
case E_BLOCK_SPRUCE_DOOR: return new cBlockDoorHandler (a_BlockType);
|
case E_BLOCK_SPRUCE_DOOR: return new cBlockDoorHandler (a_BlockType);
|
||||||
|
case E_BLOCK_SPRUCE_FENCE: return new cBlockFenceHandler (a_BlockType);
|
||||||
case E_BLOCK_SPRUCE_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
case E_BLOCK_SPRUCE_FENCE_GATE: return new cBlockFenceGateHandler (a_BlockType);
|
||||||
case E_BLOCK_SPRUCE_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
case E_BLOCK_SPRUCE_WOOD_STAIRS: return new cBlockStairsHandler (a_BlockType);
|
||||||
case E_BLOCK_STAINED_GLASS: return new cBlockGlassHandler (a_BlockType);
|
case E_BLOCK_STAINED_GLASS: return new cBlockGlassHandler (a_BlockType);
|
||||||
|
@ -555,7 +563,6 @@ void cBlockHandler::DropBlock(cChunkInterface & a_ChunkInterface, cWorldInterfac
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, const cChunk & a_Chunk)
|
bool cBlockHandler::CanBeAt(cChunkInterface & a_ChunkInterface, int a_BlockX, int a_BlockY, int a_BlockZ, const cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -611,6 +618,20 @@ bool cBlockHandler::IsInsideBlock(const Vector3d & a_Position, const BLOCKTYPE a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBoundingBox cBlockHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP)
|
||||||
|
{
|
||||||
|
if (!cBlockInfo::IsSolid(m_BlockType))
|
||||||
|
{
|
||||||
|
// Non-solid things can be placed within entities
|
||||||
|
return cBoundingBox(0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
return cBoundingBox(0, 1, 0, cBlockInfo::GetBlockHeight(m_BlockType), 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBlockHandler::Check(cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface, int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk)
|
void cBlockHandler::Check(cChunkInterface & a_ChunkInterface, cBlockPluginInterface & a_PluginInterface, int a_RelX, int a_RelY, int a_RelZ, cChunk & a_Chunk)
|
||||||
{
|
{
|
||||||
if (!CanBeAt(a_ChunkInterface, a_RelX, a_RelY, a_RelZ, a_Chunk))
|
if (!CanBeAt(a_ChunkInterface, a_RelX, a_RelY, a_RelZ, a_Chunk))
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "../Defines.h"
|
#include "../Defines.h"
|
||||||
|
|
||||||
|
#include "../BoundingBox.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,6 +32,11 @@ public:
|
||||||
Note that the coords are chunk-relative! */
|
Note that the coords are chunk-relative! */
|
||||||
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
|
virtual void OnUpdate(cChunkInterface & cChunkInterface, cWorldInterface & a_WorldInterface, cBlockPluginInterface & a_BlockPluginInterface, cChunk & a_Chunk, int a_RelX, int a_RelY, int a_RelZ);
|
||||||
|
|
||||||
|
/** Returns the relative bounding box that must be entity-free in
|
||||||
|
order for the block to be placed. a_XM, a_XP, etc. stand for the
|
||||||
|
blocktype of the minus-X neighbor, the positive-X neighbor, etc. */
|
||||||
|
virtual cBoundingBox GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP);
|
||||||
|
|
||||||
/** Called before a block is placed into a world.
|
/** Called before a block is placed into a world.
|
||||||
The handler should return true to allow placement, false to refuse.
|
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.
|
Also, the handler should set a_BlockType and a_BlockMeta to correct values for the newly placed block.
|
||||||
|
|
|
@ -35,6 +35,7 @@ SET (HDRS
|
||||||
BlockEnderchest.h
|
BlockEnderchest.h
|
||||||
BlockEntity.h
|
BlockEntity.h
|
||||||
BlockFarmland.h
|
BlockFarmland.h
|
||||||
|
BlockFence.h
|
||||||
BlockFenceGate.h
|
BlockFenceGate.h
|
||||||
BlockFire.h
|
BlockFire.h
|
||||||
BlockFlower.h
|
BlockFlower.h
|
||||||
|
|
|
@ -60,6 +60,17 @@ cBoundingBox::cBoundingBox(const cBoundingBox & a_Orig) :
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBoundingBox & cBoundingBox::operator=(const cBoundingBox & a_Other)
|
||||||
|
{
|
||||||
|
m_Min = a_Other.m_Min;
|
||||||
|
m_Max = a_Other.m_Max;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void cBoundingBox::Move(double a_OffX, double a_OffY, double a_OffZ)
|
void cBoundingBox::Move(double a_OffX, double a_OffY, double a_OffZ)
|
||||||
{
|
{
|
||||||
m_Min.x += a_OffX;
|
m_Min.x += a_OffX;
|
||||||
|
@ -119,10 +130,10 @@ cBoundingBox cBoundingBox::Union(const cBoundingBox & a_Other)
|
||||||
{
|
{
|
||||||
return cBoundingBox(
|
return cBoundingBox(
|
||||||
std::min(m_Min.x, a_Other.m_Min.x),
|
std::min(m_Min.x, a_Other.m_Min.x),
|
||||||
std::min(m_Min.y, a_Other.m_Min.y),
|
|
||||||
std::min(m_Min.z, a_Other.m_Min.z),
|
|
||||||
std::max(m_Max.x, a_Other.m_Max.x),
|
std::max(m_Max.x, a_Other.m_Max.x),
|
||||||
|
std::min(m_Min.y, a_Other.m_Min.y),
|
||||||
std::max(m_Max.y, a_Other.m_Max.y),
|
std::max(m_Max.y, a_Other.m_Max.y),
|
||||||
|
std::min(m_Min.z, a_Other.m_Min.z),
|
||||||
std::max(m_Max.z, a_Other.m_Max.z)
|
std::max(m_Max.z, a_Other.m_Max.z)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ public:
|
||||||
cBoundingBox(const Vector3d & a_Pos, double a_CubeLength);
|
cBoundingBox(const Vector3d & a_Pos, double a_CubeLength);
|
||||||
cBoundingBox(const cBoundingBox & a_Orig);
|
cBoundingBox(const cBoundingBox & a_Orig);
|
||||||
|
|
||||||
|
cBoundingBox & operator=(const cBoundingBox & a_Other);
|
||||||
|
|
||||||
/** Moves the entire boundingbox by the specified offset */
|
/** Moves the entire boundingbox by the specified offset */
|
||||||
void Move(double a_OffX, double a_OffY, double a_OffZ);
|
void Move(double a_OffX, double a_OffY, double a_OffZ);
|
||||||
|
|
||||||
|
|
|
@ -402,6 +402,9 @@ struct sSetBlock
|
||||||
|
|
||||||
/** Returns the absolute Z coord of the stored block. */
|
/** Returns the absolute Z coord of the stored block. */
|
||||||
int GetZ(void) const { return m_RelZ + cChunkDef::Width * m_ChunkZ; }
|
int GetZ(void) const { return m_RelZ + cChunkDef::Width * m_ChunkZ; }
|
||||||
|
|
||||||
|
/** Returns the absolute position of the stored block. */
|
||||||
|
Vector3i GetPos(void) const { return Vector3i(GetX(), GetY(), GetZ()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<sSetBlock> sSetBlockList;
|
typedef std::list<sSetBlock> sSetBlockList;
|
||||||
|
|
|
@ -191,6 +191,9 @@ public:
|
||||||
/** Returns the topmost class's parent class name for the object. cEntity returns an empty string (no parent). */
|
/** Returns the topmost class's parent class name for the object. cEntity returns an empty string (no parent). */
|
||||||
virtual const char * GetParentClass(void) const;
|
virtual const char * GetParentClass(void) const;
|
||||||
|
|
||||||
|
/** Returns whether blocks can be placed intersecting this entities' hitbox */
|
||||||
|
virtual bool DoesPreventBlockPlacement(void) const { return true; }
|
||||||
|
|
||||||
cWorld * GetWorld(void) const { return m_World; }
|
cWorld * GetWorld(void) const { return m_World; }
|
||||||
|
|
||||||
double GetHeadYaw (void) const { return m_HeadYaw; } // In degrees
|
double GetHeadYaw (void) const { return m_HeadYaw; } // In degrees
|
||||||
|
|
|
@ -36,6 +36,8 @@ public:
|
||||||
|
|
||||||
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
virtual void Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk) override;
|
||||||
|
|
||||||
|
virtual bool DoesPreventBlockPlacement(void) const override { return false; }
|
||||||
|
|
||||||
/** Returns whether this pickup is allowed to combine with other similar pickups */
|
/** Returns whether this pickup is allowed to combine with other similar pickups */
|
||||||
bool CanCombine(void) const { return m_bCanCombine; } // tolua_export
|
bool CanCombine(void) const { return m_bCanCombine; } // tolua_export
|
||||||
|
|
||||||
|
|
|
@ -2641,8 +2641,103 @@ void cPlayer::SendBlocksAround(int a_BlockX, int a_BlockY, int a_BlockZ, int a_R
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool cPlayer::DoesPlacingBlocksIntersectEntity(const sSetBlockVector & a_Blocks)
|
||||||
|
{
|
||||||
|
// Compute the bounding box for each block to be placed
|
||||||
|
std::vector<cBoundingBox> PlacementBoxes;
|
||||||
|
cBoundingBox PlacingBounds(0, 0, 0, 0, 0, 0);
|
||||||
|
bool HasInitializedBounds = false;
|
||||||
|
for (auto blk: a_Blocks)
|
||||||
|
{
|
||||||
|
cBlockHandler * BlockHandler = cBlockInfo::GetHandler(blk.m_BlockType);
|
||||||
|
int x = blk.GetX();
|
||||||
|
int y = blk.GetY();
|
||||||
|
int z = blk.GetZ();
|
||||||
|
cBoundingBox BlockBox = BlockHandler->GetPlacementCollisionBox(
|
||||||
|
m_World->GetBlock(x - 1, y, z),
|
||||||
|
m_World->GetBlock(x + 1, y, z),
|
||||||
|
(y == 0) ? E_BLOCK_AIR : m_World->GetBlock(x, y - 1, z),
|
||||||
|
(y == cChunkDef::Height - 1) ? E_BLOCK_AIR : m_World->GetBlock(x, y + 1, z),
|
||||||
|
m_World->GetBlock(x, y, z - 1),
|
||||||
|
m_World->GetBlock(x, y, z + 1)
|
||||||
|
);
|
||||||
|
BlockBox.Move(x, y, z);
|
||||||
|
|
||||||
|
PlacementBoxes.push_back(BlockBox);
|
||||||
|
|
||||||
|
if (HasInitializedBounds)
|
||||||
|
{
|
||||||
|
PlacingBounds = PlacingBounds.Union(BlockBox);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PlacingBounds = BlockBox;
|
||||||
|
HasInitializedBounds = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cWorld * World = GetWorld();
|
||||||
|
|
||||||
|
// Check to see if any entity intersects any block being placed
|
||||||
|
class DoesIntersectBlock : public cEntityCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const std::vector<cBoundingBox> & m_BoundingBoxes;
|
||||||
|
|
||||||
|
// The distance inside the block the entity can still be.
|
||||||
|
const double EPSILON = 0.0005;
|
||||||
|
|
||||||
|
DoesIntersectBlock(const std::vector<cBoundingBox> & a_BoundingBoxes) :
|
||||||
|
m_BoundingBoxes(a_BoundingBoxes)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Item(cEntity * a_Entity) override
|
||||||
|
{
|
||||||
|
if (!a_Entity->DoesPreventBlockPlacement())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cBoundingBox EntBox(a_Entity->GetPosition(), a_Entity->GetWidth() / 2, a_Entity->GetHeight());
|
||||||
|
for (auto BlockBox: m_BoundingBoxes)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Put in a little bit of wiggle room
|
||||||
|
BlockBox.Expand(-EPSILON, -EPSILON, -EPSILON);
|
||||||
|
if (EntBox.DoesIntersect(BlockBox))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} Callback(PlacementBoxes);
|
||||||
|
|
||||||
|
// See if any entities in that bounding box collide with anyone
|
||||||
|
if (!World->ForEachEntityInBox(PlacingBounds, Callback))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks)
|
bool cPlayer::PlaceBlocks(const sSetBlockVector & a_Blocks)
|
||||||
{
|
{
|
||||||
|
if (DoesPlacingBlocksIntersectEntity(a_Blocks))
|
||||||
|
{
|
||||||
|
// Abort - re-send all the current blocks in the a_Blocks' coords to the client:
|
||||||
|
for (auto blk2: a_Blocks)
|
||||||
|
{
|
||||||
|
m_World->SendBlockTo(blk2.GetX(), blk2.GetY(), blk2.GetZ(), this);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Call the "placing" hooks; if any fail, abort:
|
// Call the "placing" hooks; if any fail, abort:
|
||||||
cPluginManager * pm = cPluginManager::Get();
|
cPluginManager * pm = cPluginManager::Get();
|
||||||
for (auto blk: a_Blocks)
|
for (auto blk: a_Blocks)
|
||||||
|
|
|
@ -485,6 +485,9 @@ public:
|
||||||
/** Update movement-related statistics. */
|
/** Update movement-related statistics. */
|
||||||
void UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround);
|
void UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIsOnGround);
|
||||||
|
|
||||||
|
/** Whether placing the given blocks would intersect any entitiy */
|
||||||
|
bool DoesPlacingBlocksIntersectEntity(const sSetBlockVector & a_Blocks);
|
||||||
|
|
||||||
// tolua_begin
|
// tolua_begin
|
||||||
|
|
||||||
/** Returns wheter the player can fly or not. */
|
/** Returns wheter the player can fly or not. */
|
||||||
|
|
|
@ -108,6 +108,13 @@ cBlockInfo::cBlockInfoArray::cBlockInfoArray()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBoundingBox::cBoundingBox(double, double, double, double, double, double)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
|
cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
|
@ -117,6 +124,15 @@ cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBoundingBox cBlockHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP)
|
||||||
|
{
|
||||||
|
return cBoundingBox(0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cBlockHandler::GetPlacementBlockTypeMeta(
|
bool cBlockHandler::GetPlacementBlockTypeMeta(
|
||||||
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
||||||
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
||||||
|
|
|
@ -109,6 +109,14 @@ cBlockInfo::cBlockInfoArray::cBlockInfoArray()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBoundingBox::cBoundingBox(double, double, double, double, double, double)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
|
cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -117,6 +125,15 @@ cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBoundingBox cBlockHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP)
|
||||||
|
{
|
||||||
|
return cBoundingBox(0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cBlockHandler::GetPlacementBlockTypeMeta(
|
bool cBlockHandler::GetPlacementBlockTypeMeta(
|
||||||
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
||||||
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
||||||
|
|
|
@ -34,6 +34,11 @@ cBlockInfo::cBlockInfoArray::cBlockInfoArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
cBoundingBox::cBoundingBox(double, double, double, double, double, double)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -45,6 +50,15 @@ cBlockHandler::cBlockHandler(BLOCKTYPE a_BlockType)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cBoundingBox cBlockHandler::GetPlacementCollisionBox(BLOCKTYPE a_XM, BLOCKTYPE a_XP, BLOCKTYPE a_YM, BLOCKTYPE a_YP, BLOCKTYPE a_ZM, BLOCKTYPE a_ZP)
|
||||||
|
{
|
||||||
|
return cBoundingBox(0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool cBlockHandler::GetPlacementBlockTypeMeta(
|
bool cBlockHandler::GetPlacementBlockTypeMeta(
|
||||||
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
cChunkInterface & a_ChunkInterface, cPlayer * a_Player,
|
||||||
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user