void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) { Vector3i ThisPos(a_BlockX, a_BlockY, a_BlockZ); NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(ThisPos); Vector3i Direction = MetaDataToDirection(OldMeta & 0x3); if (OldMeta & 0x8) { // Was pillow if (a_ChunkInterface.GetBlock(ThisPos - Direction) == E_BLOCK_BED) { // First replace the bed with air a_ChunkInterface.FastSetBlock(ThisPos - Direction, E_BLOCK_AIR, 0); // Then destroy the bed entity Vector3i PillowPos(ThisPos - Direction); a_ChunkInterface.SetBlock(PillowPos.x, PillowPos.y, PillowPos.z, E_BLOCK_AIR, 0); } } else { // Was foot end if (a_ChunkInterface.GetBlock(ThisPos + Direction) == E_BLOCK_BED) { // First replace the bed with air a_ChunkInterface.FastSetBlock(ThisPos + Direction, E_BLOCK_AIR, 0); // Then destroy the bed entity Vector3i FootPos(ThisPos + Direction); a_ChunkInterface.SetBlock(FootPos.x, FootPos.y, FootPos.z, E_BLOCK_AIR, 0); } } }
void cBlockHandler::NeighborChanged(cChunkInterface & a_ChunkInterface, int a_NeighborX, int a_NeighborY, int a_NeighborZ, eBlockFace a_WhichNeighbor) { if ((a_NeighborY >= 0) && (a_NeighborY < cChunkDef::Height)) { cBlockInfo::GetHandler(a_ChunkInterface.GetBlock(a_NeighborX, a_NeighborY, a_NeighborZ))->OnNeighborChanged(a_ChunkInterface, a_NeighborX, a_NeighborY, a_NeighborZ, a_WhichNeighbor); } }
bool cBlockDoorHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) { UNUSED(a_WorldInterface); UNUSED(a_BlockFace); UNUSED(a_CursorX); UNUSED(a_CursorY); UNUSED(a_CursorZ); switch (a_ChunkInterface.GetBlock(a_BlockX, a_BlockY, a_BlockZ)) { default: { ASSERT(!"Unhandled door block type"); } case E_BLOCK_ACACIA_DOOR: case E_BLOCK_BIRCH_DOOR: case E_BLOCK_DARK_OAK_DOOR: case E_BLOCK_JUNGLE_DOOR: case E_BLOCK_SPRUCE_DOOR: case E_BLOCK_OAK_DOOR: { ChangeDoor(a_ChunkInterface, a_BlockX, a_BlockY, a_BlockZ); a_Player->GetWorld()->BroadcastSoundParticleEffect(EffectID::SFX_RANDOM_DOOR_OPEN_CLOSE, a_BlockX, a_BlockY, a_BlockZ, 0, a_Player->GetClientHandle()); break; } // Prevent iron door from opening on player click case E_BLOCK_IRON_DOOR: { OnCancelRightClick(a_ChunkInterface, a_WorldInterface, a_Player, a_BlockX, a_BlockY, a_BlockZ, a_BlockFace); break; } } return true; }
void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) { if (a_WorldInterface.GetDimension() != dimOverworld) { Vector3i Coords(a_BlockX, a_BlockY, a_BlockZ); a_WorldInterface.DoExplosionAt(5, a_BlockX, a_BlockY, a_BlockZ, true, esBed, &Coords); } else { if (a_WorldInterface.GetTimeOfDay() > 13000) { NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); if (Meta & 0x4) { a_Player->SendMessageFailure("This bed is occupied"); } else { Vector3i PillowDirection(0, 0, 0); if (Meta & 0x8) { // Is pillow a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX, a_BlockY, a_BlockZ); } else { // Is foot end VERIFY((Meta & 0x4) != 0x4); // Occupied flag should never be set, else our compilator (intended) is broken PillowDirection = MetaDataToDirection(Meta & 0x7); if (a_ChunkInterface.GetBlock(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z) == E_BLOCK_BED) // Must always use pillow location for sleeping { a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z); } } a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta | 0x4); // Where 0x4 = occupied bit a_Player->SetIsInBed(true); a_Player->SetBedPos(Vector3i(a_BlockX, a_BlockY, a_BlockZ)); a_Player->SendMessageSuccess("Home position set successfully"); cTimeFastForwardTester Tester; if (a_WorldInterface.ForEachPlayer(Tester)) { cPlayerBedStateUnsetter Unsetter(Vector3i(a_BlockX + PillowDirection.x, a_BlockY, a_BlockZ + PillowDirection.z), a_WorldInterface); a_WorldInterface.ForEachPlayer(Unsetter); a_WorldInterface.SetTimeOfDay(0); a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0xB); // Where 0xB = 1011, and zero is to make sure 'occupied' bit is always unset } } } else { a_Player->SendMessageFailure("You can only sleep at night"); } } }
void cBlockDoorHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) { NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); if (OldMeta & 8) { // Was upper part of door if (IsDoorBlockType(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY - 1, a_BlockZ))) { a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY - 1, a_BlockZ, E_BLOCK_AIR, 0); } } else { // Was lower part if (IsDoorBlockType(a_ChunkInterface.GetBlock(a_BlockX, a_BlockY + 1, a_BlockZ))) { a_ChunkInterface.FastSetBlock(a_BlockX, a_BlockY + 1, a_BlockZ, E_BLOCK_AIR, 0); } } }
void cBlockPistonHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) { Vector3i blockPos(a_BlockX, a_BlockY, a_BlockZ); // Get the extension of the piston NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(blockPos.x, blockPos.y, blockPos.z); blockPos += MetadataToOffset(OldMeta); if (a_ChunkInterface.GetBlock(blockPos) == E_BLOCK_PISTON_EXTENSION) { a_ChunkInterface.SetBlock(blockPos.x, blockPos.y, blockPos.z, E_BLOCK_AIR, 0); } }
void cBlockPistonHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) { NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); int newX = a_BlockX; int newY = a_BlockY; int newZ = a_BlockZ; AddPistonDir(newX, newY, newZ, OldMeta, 1); if (a_ChunkInterface.GetBlock(newX, newY, newZ) == E_BLOCK_PISTON_EXTENSION) { a_ChunkInterface.SetBlock(newX, newY, newZ, E_BLOCK_AIR, 0); } }
void cBlockBedHandler::OnDestroyed(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, int a_BlockX, int a_BlockY, int a_BlockZ) { NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); Vector3i ThisPos( a_BlockX, a_BlockY, a_BlockZ ); Vector3i Direction = MetaDataToDirection( OldMeta & 0x7 ); if (OldMeta & 0x8) { // Was pillow if (a_ChunkInterface.GetBlock(ThisPos - Direction) == E_BLOCK_BED) { a_ChunkInterface.FastSetBlock(ThisPos - Direction, E_BLOCK_AIR, 0); } } else { // Was foot end if (a_ChunkInterface.GetBlock(ThisPos + Direction) == E_BLOCK_BED) { a_ChunkInterface.FastSetBlock(ThisPos + Direction, E_BLOCK_AIR, 0); } } }
void cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) { if (a_WorldInterface.GetDimension() != dimOverworld) { Vector3i Coords(a_BlockX, a_BlockY, a_BlockZ); a_WorldInterface.DoExplosionAt(5, a_BlockX, a_BlockY, a_BlockZ, true, esBed, &Coords); } else { if (a_WorldInterface.GetTimeOfDay() > 13000) { NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); if (Meta & 0x4) { a_Player->SendMessageFailure("This bed is occupied."); } else { if (Meta & 0x8) { // Is pillow a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX, a_BlockY, a_BlockZ); } else { // Is foot end Vector3i Direction = MetaDataToDirection( Meta & 0x7 ); if (a_ChunkInterface.GetBlock(a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z) == E_BLOCK_BED) // Must always use pillow location for sleeping { a_WorldInterface.GetBroadcastManager().BroadcastUseBed(*a_Player, a_BlockX + Direction.x, a_BlockY, a_BlockZ + Direction.z); } } a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, (Meta | (1 << 2))); } } else { a_Player->SendMessageFailure("You can only sleep at night"); } } }
void cBlockPistonHeadHandler::OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) { Vector3i blockPos(a_BlockX, a_BlockY, a_BlockZ); // Get the base of the piston NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(blockPos.x, blockPos.y, blockPos.z); blockPos -= cBlockPistonHandler::MetadataToOffset(OldMeta); BLOCKTYPE Block = a_ChunkInterface.GetBlock(blockPos); if ((Block == E_BLOCK_STICKY_PISTON) || (Block == E_BLOCK_PISTON)) { a_ChunkInterface.DigBlock(a_WorldInterface, blockPos.x, blockPos.y, blockPos.z); if (a_Player->IsGameModeCreative()) { return; // No pickups if creative } cItems Pickups; Pickups.push_back(cItem(Block, 1)); a_WorldInterface.SpawnItemPickups(Pickups, blockPos.x + 0.5, blockPos.y + 0.5, blockPos.z + 0.5); } }
void cBlockPistonHeadHandler::OnDestroyedByPlayer(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ) { NIBBLETYPE OldMeta = a_ChunkInterface.GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ); int newX = a_BlockX; int newY = a_BlockY; int newZ = a_BlockZ; AddPistonDir(newX, newY, newZ, OldMeta, -1); BLOCKTYPE Block = a_ChunkInterface.GetBlock(newX, newY, newZ); if ((Block == E_BLOCK_STICKY_PISTON) || (Block == E_BLOCK_PISTON)) { a_ChunkInterface.DigBlock(a_WorldInterface, newX, newY, newZ); if (a_Player->IsGameModeCreative()) { return; // No pickups if creative } cItems Pickups; Pickups.push_back(cItem(Block, 1)); a_WorldInterface.SpawnItemPickups(Pickups, a_BlockX + 0.5, a_BlockY + 0.5, a_BlockZ + 0.5); } }
bool cBlockBedHandler::OnUse(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, cPlayer & a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, eBlockFace a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) { Vector3i Coords(a_BlockX, a_BlockY, a_BlockZ); if (a_WorldInterface.GetDimension() != dimOverworld) { a_WorldInterface.DoExplosionAt(5, a_BlockX, a_BlockY, a_BlockZ, true, esBed, &Coords); } else if (!((a_WorldInterface.GetTimeOfDay() > 12541) && (a_WorldInterface.GetTimeOfDay() < 23458))) // Source: https://minecraft.gamepedia.com/Bed#Sleeping { a_Player.SendMessageFailure("You can only sleep at night"); } else { NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(Coords); if ((Meta & 0x4) == 0x4) { a_Player.SendMessageFailure("This bed is occupied"); } else { auto FindMobs = [](cEntity & a_Entity) { return ( (a_Entity.GetEntityType() == cEntity::etMonster) && (static_cast<cMonster&>(a_Entity).GetMobFamily() == cMonster::mfHostile) ); }; if (!a_Player.GetWorld()->ForEachEntityInBox(cBoundingBox(a_Player.GetPosition() - Vector3i(0, 5, 0), 8, 10), FindMobs)) { a_Player.SendMessageFailure("You may not rest now, there are monsters nearby"); } else { Vector3i PillowDirection(0, 0, 0); if ((Meta & 0x8) == 0x8) { // Is pillow a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, { a_BlockX, a_BlockY, a_BlockZ }); } else { // Is foot end VERIFY((Meta & 0x4) != 0x4); // Occupied flag should never be set, else our compilator (intended) is broken PillowDirection = MetaDataToDirection(Meta & 0x3); if (a_ChunkInterface.GetBlock(Coords + PillowDirection) == E_BLOCK_BED) // Must always use pillow location for sleeping { a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, Vector3i{ a_BlockX, a_BlockY, a_BlockZ } + PillowDirection); } } a_Player.SetBedPos(Coords); SetBedOccupationState(a_ChunkInterface, a_Player.GetLastBedPos(), true); a_Player.SetIsInBed(true); a_Player.SendMessageSuccess("Home position set successfully"); auto TimeFastForwardTester = [](cPlayer & a_OtherPlayer) { if (!a_OtherPlayer.IsInBed()) { return true; } return false; }; if (a_WorldInterface.ForEachPlayer(TimeFastForwardTester)) { a_WorldInterface.ForEachPlayer([&](cPlayer & a_OtherPlayer) { cBlockBedHandler::SetBedOccupationState(a_ChunkInterface, a_OtherPlayer.GetLastBedPos(), false); a_OtherPlayer.SetIsInBed(false); return false; } ); a_WorldInterface.SetTimeOfDay(0); a_ChunkInterface.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta & 0x0b); // Clear the "occupied" bit of the bed's block } } } } return true; }