The bug
A spectator can occupy a bed if they enter it and then are switched to spectator mode. Expected behavior would be that the spectator would get kicked out of bed and that another player would have been able to join the bed.
How to reproduce
Place a bed and go into it. This requires the player not to be in spectator mode
/gamemode spectator
→ Notice you are still in a bedAsk another player to go into the bed you are occupying
→ Notice they can't because the bed is occupied
Linked issues
relates to 3
Attachments
Comments 17
Confirmed. The behavior with not passing night may be related to the fix for MC-47080.
Here's a code analysis along with a fix regarding this issue.
Code Analysis:
The following is based on a decompiled version of Minecraft 1.19.2 using MCP-Reborn.
net.minecraft.server.level.ServerPlayer.java
public class ServerPlayer extends Player {
...
public boolean setGameMode(GameType gameType) {
if (!this.gameMode.changeGameModeForPlayer(gameType)) {
return false;
} else {
this.connection.send(new ClientboundGameEventPacket(ClientboundGameEventPacket.CHANGE_GAME_MODE, (float)gameType.getId()));
if (gameType == GameType.SPECTATOR) {
this.removeEntitiesOnShoulder();
this.stopRiding();
} else {
this.setCamera(this);
}
this.onUpdateAbilities();
this.updateEffectVisibility();
return true;
}
}
...
If we look at the above class, we can see that only two methods are called when a player switches into spectator mode. These methods are removeEntitiesOnShoulder()
and stopRiding()
. This basically means that when a player changes into spectator mode, any entities that are riding on their shoulders will be dismounted, along with the player themselves being dismounted if they are riding any entity. As a result of only these two methods being called, the player can continue to sleep in a bed even after switching into spectator mode.
Fix:
Simply calling the stopSleeping()
method where appropriate within this piece of code will stop players from sleeping in beds upon switching into spectator mode, thus resolving this problem. The following line code can be used to fix this issue.
this.stopSleeping();
Following on from my code analysis, I've double-checked my proposed fix and I can confidently confirm that it's fully functioning and works as expected, so I've attached two screenshots to this report, one of which shows the current code and the other that shows the fixed code. I feel this information may be quite insightful hence my reasoning for providing it. 🙂
[media][media]
First part confirmed. In single player mode, Night doesn't get skipped.