summaryrefslogtreecommitdiffstats
path: root/src/Blocks/BlockBed.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Blocks/BlockBed.cpp')
-rw-r--r--src/Blocks/BlockBed.cpp150
1 files changed, 82 insertions, 68 deletions
diff --git a/src/Blocks/BlockBed.cpp b/src/Blocks/BlockBed.cpp
index 8b349ef5e..6d50e8c41 100644
--- a/src/Blocks/BlockBed.cpp
+++ b/src/Blocks/BlockBed.cpp
@@ -15,7 +15,11 @@
-void cBlockBedHandler::OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface, Vector3i a_BlockPos, BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta)
+void cBlockBedHandler::OnBroken(
+ cChunkInterface & a_ChunkInterface, cWorldInterface & a_WorldInterface,
+ const Vector3i a_BlockPos,
+ BLOCKTYPE a_OldBlockType, NIBBLETYPE a_OldBlockMeta
+)
{
auto Direction = MetaDataToDirection(a_OldBlockMeta & 0x03);
if ((a_OldBlockMeta & 0x08) != 0)
@@ -50,87 +54,97 @@ void cBlockBedHandler::OnBroken(cChunkInterface & a_ChunkInterface, cWorldInterf
-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)
+bool cBlockBedHandler::OnUse(
+ cChunkInterface & a_ChunkInterface,
+ cWorldInterface & a_WorldInterface,
+ cPlayer & a_Player,
+ const Vector3i a_BlockPos,
+ eBlockFace a_BlockFace,
+ const Vector3i a_CursorPos
+)
{
- Vector3i Coords(a_BlockX, a_BlockY, a_BlockZ);
+ // Sleeping in bed only allowed in Overworld, beds explode elsewhere:
if (a_WorldInterface.GetDimension() != dimOverworld)
{
- a_WorldInterface.DoExplosionAt(5, a_BlockX, a_BlockY, a_BlockZ, true, esBed, &Coords);
+ auto PosCopy = a_BlockPos;
+ a_WorldInterface.DoExplosionAt(5, a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, true, esBed, &PosCopy);
+ return true;
}
- else if (!((a_WorldInterface.GetTimeOfDay() > 12541) && (a_WorldInterface.GetTimeOfDay() < 23458))) // Source: https://minecraft.gamepedia.com/Bed#Sleeping
+
+ // Sleeping is allowed only during night:
+ // TODO: Also during thunderstorms
+ 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");
+ return true;
+ }
+
+ // Check if the bed is occupied:
+ auto Meta = a_ChunkInterface.GetBlockMeta(a_BlockPos);
+ if ((Meta & 0x04) == 0x04)
+ {
+ a_Player.SendMessageFailure("This bed is occupied");
+ return true;
+ }
+
+ // Cannot sleep if there are hostile mobs nearby:
+ 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");
+ return true;
+ }
+
+ // Broadcast the "Use bed" for the pillow block:
+ if ((Meta & 0x8) == 0x8)
+ {
+ // Is pillow
+ a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, a_BlockPos);
}
else
{
- NIBBLETYPE Meta = a_ChunkInterface.GetBlockMeta(Coords);
- if ((Meta & 0x4) == 0x4)
+ // Is foot end
+ VERIFY((Meta & 0x04) != 0x04); // Occupied flag should never be set, else our compilator (intended) is broken
+
+ auto PillowPos = a_BlockPos + MetaDataToDirection(Meta & 0x03);
+ if (a_ChunkInterface.GetBlock(PillowPos) == E_BLOCK_BED) // Must always use pillow location for sleeping
{
- a_Player.SendMessageFailure("This bed is occupied");
+ a_WorldInterface.GetBroadcastManager().BroadcastUseBed(a_Player, PillowPos);
}
- 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
+ // Occupy the bed:
+ a_Player.SetBedPos(a_BlockPos);
+ SetBedOccupationState(a_ChunkInterface, a_Player.GetLastBedPos(), true);
+ a_Player.SetIsInBed(true);
+ a_Player.SendMessageSuccess("Home position set successfully");
+
+ // Fast-forward the time if all players in the world are in their beds:
+ auto TimeFastForwardTester = [](cPlayer & a_OtherPlayer)
+ {
+ if (!a_OtherPlayer.IsInBed())
+ {
+ return true;
+ }
+ return false;
+ };
+ if (a_WorldInterface.ForEachPlayer(TimeFastForwardTester))
+ {
+ a_WorldInterface.ForEachPlayer([&](cPlayer & a_OtherPlayer)
{
- 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
- }
+ cBlockBedHandler::SetBedOccupationState(a_ChunkInterface, a_OtherPlayer.GetLastBedPos(), false);
+ a_OtherPlayer.SetIsInBed(false);
+ return false;
}
- }
+ );
+ a_WorldInterface.SetTimeOfDay(0);
+ a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta & 0x0b); // Clear the "occupied" bit of the bed's block
}
return true;
}