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.ingame.client.player.ClientPlayerPositionRotationPacket;
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.packetlib.BuiltinFlags;
import com.github.steveice10.packetlib.Client;
@ -95,7 +94,6 @@ import java.security.spec.InvalidKeySpecException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;
@Getter
public class GeyserSession implements CommandSender {
@ -148,7 +146,11 @@ public class GeyserSession implements CommandSender {
@Setter
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;
@ -185,9 +187,6 @@ public class GeyserSession implements CommandSender {
@Setter
private Vector3i lastInteractionPosition = Vector3i.ZERO;
private boolean manyDimPackets = false;
private ServerRespawnPacket lastDimPacket = null;
@Setter
private Entity ridingVehicleEntity;
@ -537,16 +536,6 @@ public class GeyserSession implements CommandSender {
@Override
public void packetReceived(PacketReceivedEvent event) {
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
if (event.getPacket() instanceof LoginSuccessPacket) {
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.translators.PacketTranslator;
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.utils.BlockUtils;
@ -157,14 +156,12 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
// Handled in BedrockInventoryTransactionTranslator
break;
case DIMENSION_CHANGE_SUCCESS:
if (session.getPendingDimSwitches().decrementAndGet() == 0) {
//sometimes the client doesn't feel like loading
PlayStatusPacket spawnPacket = new PlayStatusPacket();
spawnPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN);
session.sendUpstreamPacket(spawnPacket);
entity.updateBedrockAttributes(session);
session.getEntityCache().updateBossBars();
}
//sometimes the client doesn't feel like loading
PlayStatusPacket spawnPacket = new PlayStatusPacket();
spawnPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN);
session.sendUpstreamPacket(spawnPacket);
entity.updateBedrockAttributes(session);
session.getEntityCache().updateBossBars();
break;
case JUMP:
session.setJumping(true);

View file

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

View file

@ -55,12 +55,12 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke
// are swapping servers
String newDimension = DimensionUtils.getNewDimension(packet.getDimension());
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, newDimension);
session.getWorldCache().removeScoreboard();
}
session.setWorldName(packet.getWorldName());
AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket();
bedrockPacket.setUniqueEntityId(session.getPlayerEntity().getGeyserId());

View file

@ -43,8 +43,6 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
@Override
public void translate(ServerRespawnPacket packet, GeyserSession session) {
Entity entity = session.getPlayerEntity();
if (entity == null)
return;
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
@ -66,18 +64,24 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket>
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());
if (!session.getDimension().equals(newDimension)) {
DimensionUtils.switchDimension(session, newDimension);
} else {
if (session.isManyDimPackets()) { //reloading world
String fakeDim = session.getDimension().equals(DimensionUtils.OVERWORLD) ? DimensionUtils.NETHER : DimensionUtils.OVERWORLD;
if (!session.getDimension().equals(newDimension) || !packet.getWorldName().equals(session.getWorldName())) {
if (!packet.getWorldName().equals(session.getWorldName()) && session.getDimension().equals(newDimension)) {
// Switching to a new world (based off the world name change); send a fake dimension change
String fakeDim = DimensionUtils.getTemporaryDimension(session.getDimension(), newDimension);
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
public void translate(ServerPlayerPositionRotationPacket packet, GeyserSession session) {
PlayerEntity entity = session.getPlayerEntity();
if (entity == null)
return;
if (!session.isLoggedIn())
return;
PlayerEntity entity = session.getPlayerEntity();
if (!session.isSpawned()) {
Vector3f pos = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
entity.setPosition(pos);

View file

@ -57,8 +57,6 @@ public class DimensionUtils {
public static void switchDimension(GeyserSession session, String javaDimension) {
int bedrockDimension = javaToBedrock(javaDimension);
Entity player = session.getPlayerEntity();
if (javaDimension.equals(session.getDimension()))
return;
if (session.getMovementSendIfIdle() != null) {
session.getMovementSendIfIdle().cancel(true);
@ -67,9 +65,6 @@ public class DimensionUtils {
session.getEntityCache().removeAllEntities();
session.getItemFrameCache().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);
@ -150,4 +145,20 @@ public class DimensionUtils {
// Change dimension ID to the End to allow for building above Bedrock
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;
}
}