Support immediate respawn gamerule (#970)

* Support immediate respawn gamerule

This commit now supports immediate respawn if the server enables it - both on the setting being applied on join and the setting being modified in-game. This also refactors the respawning process to more closely match BDS behavior - nothing broke in my testing but more testing is needed.

* Reuse spawned variable instead of creating new variable
This commit is contained in:
Camotoy 2020-07-30 16:31:12 -04:00 committed by GitHub
parent a4339be212
commit 238a3a8df1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 33 additions and 21 deletions

View file

@ -35,6 +35,8 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.LevelEventType;
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket;
import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket;
@ -60,8 +62,12 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
switch (packet.getAction()) {
case RESPAWN:
// Don't put anything here as respawn is already handled
// in BedrockRespawnTranslator
// Respawn process is finished and the server and client are both OK with respawning.
EntityEventPacket eventPacket = new EntityEventPacket();
eventPacket.setRuntimeEntityId(entity.getGeyserId());
eventPacket.setType(EntityEventType.RESPAWN);
eventPacket.setData(0);
session.sendUpstreamPacket(eventPacket);
break;
case START_SWIMMING:
ClientPlayerStatePacket startSwimPacket = new ClientPlayerStatePacket((int) entity.getEntityId(), PlayerState.START_SPRINTING);

View file

@ -39,11 +39,13 @@ public class BedrockRespawnTranslator extends PacketTranslator<RespawnPacket> {
@Override
public void translate(RespawnPacket packet, GeyserSession session) {
if (packet.getState() == RespawnPacket.State.CLIENT_READY) {
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.setRuntimeEntityId(0);
respawnPacket.setPosition(Vector3f.ZERO);
respawnPacket.setState(RespawnPacket.State.SERVER_SEARCHING);
session.sendUpstreamPacket(respawnPacket);
if (!session.isSpawned()) { // Otherwise when immediate respawn is on the client never loads
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.setRuntimeEntityId(0);
respawnPacket.setPosition(Vector3f.ZERO);
respawnPacket.setState(RespawnPacket.State.SERVER_SEARCHING);
session.sendUpstreamPacket(respawnPacket);
}
ClientRequestPacket javaRespawnPacket = new ClientRequestPacket(ClientRequest.RESPAWN);
session.sendDownstreamPacket(javaRespawnPacket);

View file

@ -30,11 +30,9 @@ import com.github.steveice10.mc.protocol.data.game.setting.ChatVisibility;
import com.github.steveice10.mc.protocol.data.game.setting.SkinPart;
import com.github.steveice10.mc.protocol.packet.ingame.client.ClientSettingsPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket;
import com.nukkitx.protocol.bedrock.data.GameRuleData;
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket;
import com.nukkitx.protocol.bedrock.packet.PlayStatusPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket;
import com.nukkitx.protocol.bedrock.packet.*;
import org.geysermc.connector.entity.PlayerEntity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
@ -80,6 +78,11 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke
entityDataPacket.getMetadata().putAll(entity.getMetadata());
session.sendUpstreamPacket(entityDataPacket);
// Send if client should show respawn screen
GameRulesChangedPacket gamerulePacket = new GameRulesChangedPacket();
gamerulePacket.getGameRules().add(new GameRuleData<>("doimmediaterespawn", !packet.isEnableRespawnScreen()));
session.sendUpstreamPacket(gamerulePacket);
session.setRenderDistance(packet.getViewDistance());
// We need to send our skin parts to the server otherwise java sees us with no hat, jacket etc

View file

@ -29,8 +29,6 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.PositionElement
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityEventType;
import com.nukkitx.protocol.bedrock.packet.EntityEventPacket;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
@ -61,17 +59,11 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator<Serve
entity.setRotation(Vector3f.from(packet.getYaw(), packet.getPitch(), packet.getYaw()));
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.setRuntimeEntityId(entity.getGeyserId());
respawnPacket.setRuntimeEntityId(0); // Bedrock server behavior
respawnPacket.setPosition(entity.getPosition());
respawnPacket.setState(RespawnPacket.State.SERVER_READY);
session.sendUpstreamPacket(respawnPacket);
EntityEventPacket eventPacket = new EntityEventPacket();
eventPacket.setRuntimeEntityId(entity.getGeyserId());
eventPacket.setType(EntityEventType.RESPAWN);
eventPacket.setData(0);
session.sendUpstreamPacket(eventPacket);
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
entityDataPacket.setRuntimeEntityId(entity.getGeyserId());
entityDataPacket.getMetadata().putAll(entity.getMetadata());
@ -81,7 +73,7 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator<Serve
movePlayerPacket.setRuntimeEntityId(entity.getGeyserId());
movePlayerPacket.setPosition(entity.getPosition());
movePlayerPacket.setRotation(Vector3f.from(packet.getPitch(), packet.getYaw(), 0));
movePlayerPacket.setMode(MovePlayerPacket.Mode.RESPAWN); //TODO: PROBABLY RIGHT BUT STILL CHECK
movePlayerPacket.setMode(MovePlayerPacket.Mode.RESPAWN);
session.sendUpstreamPacket(movePlayerPacket);
session.setSpawned(true);

View file

@ -28,10 +28,12 @@ package org.geysermc.connector.network.translators.java.world;
import com.github.steveice10.mc.protocol.data.game.ClientRequest;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.world.notify.EnterCreditsValue;
import com.github.steveice10.mc.protocol.data.game.world.notify.RespawnScreenValue;
import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerNotifyClientPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.AdventureSetting;
import com.nukkitx.protocol.bedrock.data.GameRuleData;
import com.nukkitx.protocol.bedrock.data.LevelEventType;
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
@ -129,6 +131,13 @@ public class JavaNotifyClientTranslator extends PacketTranslator<ServerNotifyCli
eventPacket.setData(0);
eventPacket.setRuntimeEntityId(entity.getGeyserId());
session.sendUpstreamPacket(eventPacket);
break;
case ENABLE_RESPAWN_SCREEN:
GameRulesChangedPacket gamerulePacket = new GameRulesChangedPacket();
gamerulePacket.getGameRules().add(new GameRuleData<>("doimmediaterespawn",
packet.getValue() == RespawnScreenValue.IMMEDIATE_RESPAWN));
session.sendUpstreamPacket(gamerulePacket);
break;
default:
break;
}