Dimension switching cleanup (#1694)

* Dimension switching cleanup

Cleans up dimension switching logic that should no longer be needed. Also fixes above Nether Bedrock building dimension switching.

* Clear thunder on dimension switch too

* Clarify fake dimension switch function name

* Javadoc that
This commit is contained in:
Camotoy 2021-01-03 19:06:20 -05:00 committed by GitHub
parent 3f7d669676
commit 50b80a64d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 47 additions and 48 deletions

View File

@ -37,7 +37,6 @@ import com.github.steveice10.mc.protocol.data.game.window.VillagerTrade;
import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket; import com.github.steveice10.mc.protocol.packet.handshake.client.HandshakePacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPositionRotationPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket; import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientTeleportConfirmPacket;
import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket;
import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket; import com.github.steveice10.mc.protocol.packet.login.server.LoginSuccessPacket;
import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.BuiltinFlags;
import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.Client;
@ -95,7 +94,6 @@ import java.security.spec.InvalidKeySpecException;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;
@Getter @Getter
public class GeyserSession implements CommandSender { public class GeyserSession implements CommandSender {
@ -148,7 +146,11 @@ public class GeyserSession implements CommandSender {
@Setter @Setter
private GameMode gameMode = GameMode.SURVIVAL; private GameMode gameMode = GameMode.SURVIVAL;
private final AtomicInteger pendingDimSwitches = new AtomicInteger(0); /**
* Keeps track of the world name for respawning.
*/
@Setter
private String worldName = null;
private boolean sneaking; private boolean sneaking;
@ -185,9 +187,6 @@ public class GeyserSession implements CommandSender {
@Setter @Setter
private Vector3i lastInteractionPosition = Vector3i.ZERO; private Vector3i lastInteractionPosition = Vector3i.ZERO;
private boolean manyDimPackets = false;
private ServerRespawnPacket lastDimPacket = null;
@Setter @Setter
private Entity ridingVehicleEntity; private Entity ridingVehicleEntity;
@ -537,16 +536,6 @@ public class GeyserSession implements CommandSender {
@Override @Override
public void packetReceived(PacketReceivedEvent event) { public void packetReceived(PacketReceivedEvent event) {
if (!closed) { if (!closed) {
//handle consecutive respawn packets
if (event.getPacket().getClass().equals(ServerRespawnPacket.class)) {
manyDimPackets = lastDimPacket != null;
lastDimPacket = event.getPacket();
return;
} else if (lastDimPacket != null) {
PacketTranslatorRegistry.JAVA_TRANSLATOR.translate(lastDimPacket.getClass(), lastDimPacket, GeyserSession.this);
lastDimPacket = null;
}
// Required, or else Floodgate players break with Bukkit chunk caching // Required, or else Floodgate players break with Bukkit chunk caching
if (event.getPacket() instanceof LoginSuccessPacket) { if (event.getPacket() instanceof LoginSuccessPacket) {
GameProfile profile = ((LoginSuccessPacket) event.getPacket()).getProfile(); GameProfile profile = ((LoginSuccessPacket) event.getPacket()).getProfile();

View File

@ -43,7 +43,6 @@ import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession; import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator; import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator; import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.network.translators.collision.CollisionManager;
import org.geysermc.connector.network.translators.world.block.BlockTranslator; import org.geysermc.connector.network.translators.world.block.BlockTranslator;
import org.geysermc.connector.utils.BlockUtils; import org.geysermc.connector.utils.BlockUtils;
@ -157,14 +156,12 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
// Handled in BedrockInventoryTransactionTranslator // Handled in BedrockInventoryTransactionTranslator
break; break;
case DIMENSION_CHANGE_SUCCESS: case DIMENSION_CHANGE_SUCCESS:
if (session.getPendingDimSwitches().decrementAndGet() == 0) { //sometimes the client doesn't feel like loading
//sometimes the client doesn't feel like loading PlayStatusPacket spawnPacket = new PlayStatusPacket();
PlayStatusPacket spawnPacket = new PlayStatusPacket(); spawnPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN);
spawnPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); session.sendUpstreamPacket(spawnPacket);
session.sendUpstreamPacket(spawnPacket); entity.updateBedrockAttributes(session);
entity.updateBedrockAttributes(session); session.getEntityCache().updateBossBars();
session.getEntityCache().updateBossBars();
}
break; break;
case JUMP: case JUMP:
session.setJumping(true); session.setJumping(true);

View File

@ -50,7 +50,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
@Override @Override
public void translate(MovePlayerPacket packet, GeyserSession session) { public void translate(MovePlayerPacket packet, GeyserSession session) {
PlayerEntity entity = session.getPlayerEntity(); PlayerEntity entity = session.getPlayerEntity();
if (!session.isSpawned() || session.getPendingDimSwitches().get() > 0) return; if (!session.isSpawned()) return;
if (!session.getUpstream().isInitialized()) { if (!session.getUpstream().isInitialized()) {
MoveEntityAbsolutePacket moveEntityBack = new MoveEntityAbsolutePacket(); MoveEntityAbsolutePacket moveEntityBack = new MoveEntityAbsolutePacket();

View File

@ -55,12 +55,12 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke
// are swapping servers // are swapping servers
String newDimension = DimensionUtils.getNewDimension(packet.getDimension()); String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
if (session.isSpawned()) { if (session.isSpawned()) {
String fakeDim = session.getDimension().equals(DimensionUtils.OVERWORLD) ? DimensionUtils.NETHER : DimensionUtils.OVERWORLD; String fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), newDimension);
DimensionUtils.switchDimension(session, fakeDim); DimensionUtils.switchDimension(session, fakeDim);
DimensionUtils.switchDimension(session, newDimension);
session.getWorldCache().removeScoreboard(); session.getWorldCache().removeScoreboard();
} }
session.setWorldName(packet.getWorldName());
AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket(); AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket();
bedrockPacket.setUniqueEntityId(session.getPlayerEntity().getGeyserId()); bedrockPacket.setUniqueEntityId(session.getPlayerEntity().getGeyserId());

View File

@ -43,8 +43,6 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
@Override @Override
public void translate(ServerRespawnPacket packet, GeyserSession session) { public void translate(ServerRespawnPacket packet, GeyserSession session) {
Entity entity = session.getPlayerEntity(); Entity entity = session.getPlayerEntity();
if (entity == null)
return;
float maxHealth = entity.getAttributes().containsKey(AttributeType.MAX_HEALTH) ? entity.getAttributes().get(AttributeType.MAX_HEALTH).getValue() : 20f; float maxHealth = entity.getAttributes().containsKey(AttributeType.MAX_HEALTH) ? entity.getAttributes().get(AttributeType.MAX_HEALTH).getValue() : 20f;
// Max health must be divisible by two in bedrock // Max health must be divisible by two in bedrock
@ -66,18 +64,24 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
session.setRaining(false); session.setRaining(false);
} }
if (session.isThunder()) {
LevelEventPacket stopThunderPacket = new LevelEventPacket();
stopThunderPacket.setType(LevelEventType.STOP_THUNDERSTORM);
stopThunderPacket.setData(0);
stopThunderPacket.setPosition(Vector3f.ZERO);
session.sendUpstreamPacket(stopThunderPacket);
session.setThunder(false);
}
String newDimension = DimensionUtils.getNewDimension(packet.getDimension()); String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
if (!session.getDimension().equals(newDimension)) { if (!session.getDimension().equals(newDimension) || !packet.getWorldName().equals(session.getWorldName())) {
DimensionUtils.switchDimension(session, newDimension); if (!packet.getWorldName().equals(session.getWorldName()) && session.getDimension().equals(newDimension)) {
} else { // Switching to a new world (based off the world name change); send a fake dimension change
if (session.isManyDimPackets()) { //reloading world String fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), newDimension);
String fakeDim = session.getDimension().equals(DimensionUtils.OVERWORLD) ? DimensionUtils.NETHER : DimensionUtils.OVERWORLD;
DimensionUtils.switchDimension(session, fakeDim); DimensionUtils.switchDimension(session, fakeDim);
DimensionUtils.switchDimension(session, newDimension);
} else {
// Handled in JavaPlayerPositionRotationTranslator
session.setSpawned(false);
} }
session.setWorldName(packet.getWorldName());
DimensionUtils.switchDimension(session, newDimension);
} }
} }
} }

View File

@ -46,13 +46,11 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator<Serve
@Override @Override
public void translate(ServerPlayerPositionRotationPacket packet, GeyserSession session) { public void translate(ServerPlayerPositionRotationPacket packet, GeyserSession session) {
PlayerEntity entity = session.getPlayerEntity();
if (entity == null)
return;
if (!session.isLoggedIn()) if (!session.isLoggedIn())
return; return;
PlayerEntity entity = session.getPlayerEntity();
if (!session.isSpawned()) { if (!session.isSpawned()) {
Vector3f pos = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); Vector3f pos = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
entity.setPosition(pos); entity.setPosition(pos);

View File

@ -57,8 +57,6 @@ public class DimensionUtils {
public static void switchDimension(GeyserSession session, String javaDimension) { public static void switchDimension(GeyserSession session, String javaDimension) {
int bedrockDimension = javaToBedrock(javaDimension); int bedrockDimension = javaToBedrock(javaDimension);
Entity player = session.getPlayerEntity(); Entity player = session.getPlayerEntity();
if (javaDimension.equals(session.getDimension()))
return;
if (session.getMovementSendIfIdle() != null) { if (session.getMovementSendIfIdle() != null) {
session.getMovementSendIfIdle().cancel(true); session.getMovementSendIfIdle().cancel(true);
@ -67,9 +65,6 @@ public class DimensionUtils {
session.getEntityCache().removeAllEntities(); session.getEntityCache().removeAllEntities();
session.getItemFrameCache().clear(); session.getItemFrameCache().clear();
session.getSkullCache().clear(); session.getSkullCache().clear();
if (session.getPendingDimSwitches().getAndIncrement() > 0) {
ChunkUtils.sendEmptyChunks(session, player.getPosition().toInt(), 3, true);
}
Vector3i pos = Vector3i.from(0, Short.MAX_VALUE, 0); Vector3i pos = Vector3i.from(0, Short.MAX_VALUE, 0);
@ -150,4 +145,20 @@ public class DimensionUtils {
// Change dimension ID to the End to allow for building above Bedrock // Change dimension ID to the End to allow for building above Bedrock
BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? 2 : 1; BEDROCK_NETHER_ID = isAboveNetherBedrockBuilding ? 2 : 1;
} }
/**
* Gets the fake, temporary dimension we send clients to so we aren't switching to the same dimension without an additional
* dimension switch.
*
* @param currentDimension the current dimension of the player
* @param newDimension the new dimension that the player will be transferred to
* @return the fake dimension to transfer to
*/
public static String getTemporaryDimension(String currentDimension, String newDimension) {
if (BEDROCK_NETHER_ID == 2) {
// Prevents rare instances of Bedrock locking up
return javaToBedrock(newDimension) == 2 ? OVERWORLD : NETHER;
}
return currentDimension.equals(OVERWORLD) ? NETHER : OVERWORLD;
}
} }