forked from GeyserMC/Geyser
		
	Rewrite dimension code
New code does not rely on pausing the thread
This commit is contained in:
		
							parent
							
								
									8efeb3fe25
								
							
						
					
					
						commit
						b2f86ec20b
					
				
					 10 changed files with 56 additions and 102 deletions
				
			
		|  | @ -57,8 +57,7 @@ import org.geysermc.connector.entity.PlayerEntity; | |||
| import org.geysermc.connector.inventory.PlayerInventory; | ||||
| import org.geysermc.connector.network.session.cache.*; | ||||
| import org.geysermc.connector.network.translators.Registry; | ||||
| import org.geysermc.connector.network.translators.TranslatorsInit; | ||||
| import org.geysermc.connector.utils.DimensionUtils; | ||||
| import org.geysermc.connector.utils.ChunkUtils; | ||||
| import org.geysermc.connector.utils.Toolbox; | ||||
| 
 | ||||
| import java.net.InetSocketAddress; | ||||
|  | @ -100,8 +99,8 @@ public class GeyserSession implements Player { | |||
|     private GameMode gameMode = GameMode.SURVIVAL; | ||||
| 
 | ||||
|     @Setter | ||||
|     private volatile boolean switchingDim = false; | ||||
|     private final Object dimensionLock = new Object(); | ||||
|     private boolean switchingDimension = false; | ||||
|     private boolean manyDimPackets = false; | ||||
|     private ServerRespawnPacket lastDimPacket = null; | ||||
| 
 | ||||
|     public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { | ||||
|  | @ -128,25 +127,8 @@ public class GeyserSession implements Player { | |||
|     public void connect(RemoteServer remoteServer) { | ||||
|         startGame(); | ||||
|         this.remoteServer = remoteServer; | ||||
|         if (!(connector.getConfig().getRemote().getAuthType().hashCode() == "online".hashCode())) { | ||||
|             connector.getLogger().info("Attempting to login using offline mode... authentication is disabled."); | ||||
|             authenticate(authenticationData.getName()); | ||||
|         } | ||||
| 
 | ||||
|         Vector3f pos = Vector3f.ZERO; | ||||
|         int chunkX = pos.getFloorX() >> 4; | ||||
|         int chunkZ = pos.getFloorZ() >> 4; | ||||
|         NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); | ||||
|         chunkPublisherUpdatePacket.setPosition(pos.toInt()); | ||||
|         chunkPublisherUpdatePacket.setRadius(renderDistance << 4); | ||||
|         upstream.sendPacket(chunkPublisherUpdatePacket); | ||||
| 
 | ||||
|         LevelChunkPacket data = new LevelChunkPacket(); | ||||
|         data.setChunkX(chunkX); | ||||
|         data.setChunkZ(chunkZ); | ||||
|         data.setSubChunksLength(0); | ||||
|         data.setData(TranslatorsInit.EMPTY_LEVEL_CHUNK_DATA); | ||||
|         upstream.sendPacket(data); | ||||
|         ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 5); | ||||
| 
 | ||||
|         BiomeDefinitionListPacket biomePacket = new BiomeDefinitionListPacket(); | ||||
|         biomePacket.setTag(CompoundTag.EMPTY); | ||||
|  | @ -207,9 +189,7 @@ public class GeyserSession implements Player { | |||
|                         if (!closed) { | ||||
|                             //handle consecutive respawn packets | ||||
|                             if (event.getPacket().getClass().equals(ServerRespawnPacket.class)) { | ||||
|                                 if (lastDimPacket != null) { | ||||
|                                     DimensionUtils.switchDimension(GeyserSession.this, lastDimPacket.getDimension(), true); | ||||
|                                 } | ||||
|                                 manyDimPackets = lastDimPacket != null; | ||||
|                                 lastDimPacket = event.getPacket(); | ||||
|                                 return; | ||||
|                             } else if (lastDimPacket != null) { | ||||
|  |  | |||
|  | @ -73,6 +73,13 @@ public class EntityCache { | |||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     public void removeAllEntities() { | ||||
|         List<Entity> entities = new ArrayList<>(session.getEntityCache().getEntities().values()); | ||||
|         for (Entity entity : entities) { | ||||
|             session.getEntityCache().removeEntity(entity, false); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public Entity getEntityByGeyserId(long geyserId) { | ||||
|         return entities.get(geyserId); | ||||
|     } | ||||
|  |  | |||
|  | @ -34,9 +34,7 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye | |||
| import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerPlaceBlockPacket; | ||||
| import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket; | ||||
| import com.nukkitx.math.vector.Vector3i; | ||||
| import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; | ||||
| import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket; | ||||
| import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; | ||||
| import org.geysermc.connector.entity.Entity; | ||||
| import org.geysermc.connector.network.session.GeyserSession; | ||||
| import org.geysermc.connector.network.translators.PacketTranslator; | ||||
|  | @ -108,10 +106,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket | |||
|                 // Handled in BedrockInventoryTransactionTranslator | ||||
|                 break; | ||||
|             case DIMENSION_CHANGE_SUCCESS: | ||||
|                 synchronized (session.getDimensionLock()) { | ||||
|                     session.setSwitchingDim(false); | ||||
|                     session.getDimensionLock().notifyAll(); | ||||
|                 } | ||||
|                 session.setSwitchingDimension(false); | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack | |||
|     @Override | ||||
|     public void translate(MovePlayerPacket packet, GeyserSession session) { | ||||
|         PlayerEntity entity = session.getPlayerEntity(); | ||||
|         if (entity == null || !session.isSpawned() || session.isSwitchingDim()) return; | ||||
|         if (entity == null || !session.isSpawned() || session.isSwitchingDimension()) return; | ||||
| 
 | ||||
|         if (!session.getUpstream().isInitialized()) { | ||||
|             MoveEntityAbsolutePacket moveEntityBack = new MoveEntityAbsolutePacket(); | ||||
|  |  | |||
|  | @ -13,6 +13,11 @@ public class BedrockPlayerInitializedTranslator extends PacketTranslator<SetLoca | |||
|             if (!session.getUpstream().isInitialized()) { | ||||
|                 session.getUpstream().setInitialized(true); | ||||
| 
 | ||||
|                 if (!(session.getConnector().getConfig().getRemote().getAuthType().hashCode() == "online".hashCode())) { | ||||
|                     session.getConnector().getLogger().info("Attempting to login using offline mode... authentication is disabled."); | ||||
|                     session.authenticate(session.getAuthenticationData().getName()); | ||||
|                 } | ||||
| 
 | ||||
|                 for (PlayerEntity entity : session.getEntityCache().getEntitiesByType(PlayerEntity.class)) { | ||||
|                     if (!entity.isValid()) { | ||||
|                         // async skin loading | ||||
|  | @ -21,9 +26,5 @@ public class BedrockPlayerInitializedTranslator extends PacketTranslator<SetLoca | |||
|                 } | ||||
|             } | ||||
|         } | ||||
|         synchronized (session.getDimensionLock()) { | ||||
|             session.setSwitchingDim(false); | ||||
|             session.getDimensionLock().notifyAll(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -40,15 +40,6 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke | |||
|         PlayerEntity entity = session.getPlayerEntity(); | ||||
|         entity.setEntityId(packet.getEntityId()); | ||||
| 
 | ||||
|         if (DimensionUtils.javaToBedrock(packet.getDimension()) != entity.getDimension()) { | ||||
|             if (!session.getUpstream().isInitialized()) { | ||||
|                 session.setSwitchingDim(true); | ||||
|                 DimensionUtils.sendEmptyChunks(session, entity.getPosition().toInt()); | ||||
|                 DimensionUtils.waitForAck(session); | ||||
|             } | ||||
|             DimensionUtils.switchDimension(session, packet.getDimension(), false); | ||||
|         } | ||||
| 
 | ||||
|         AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket(); | ||||
|         bedrockPacket.setUniqueEntityId(session.getPlayerEntity().getGeyserId()); | ||||
|         bedrockPacket.setPlayerPermission(1); | ||||
|  | @ -74,5 +65,9 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke | |||
|         ChunkRadiusUpdatedPacket chunkRadiusPacket = new ChunkRadiusUpdatedPacket(); | ||||
|         chunkRadiusPacket.setRadius(session.getRenderDistance()); | ||||
|         session.getUpstream().sendPacket(chunkRadiusPacket); | ||||
| 
 | ||||
|         if (DimensionUtils.javaToBedrock(packet.getDimension()) != entity.getDimension()) { | ||||
|             DimensionUtils.switchDimension(session, packet.getDimension()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -46,8 +46,12 @@ public class JavaRespawnTranslator extends PacketTranslator<ServerRespawnPacket> | |||
|         session.setGameMode(packet.getGamemode()); | ||||
| 
 | ||||
|         if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { | ||||
|             DimensionUtils.switchDimension(session, packet.getDimension(), false); | ||||
|             DimensionUtils.switchDimension(session, packet.getDimension()); | ||||
|         } else { | ||||
|             if (session.isManyDimPackets()) { //reloading world | ||||
|                 session.getEntityCache().removeAllEntities(); | ||||
|                 //TODO: fix lighting bug | ||||
|             } | ||||
|             // Handled in JavaPlayerPositionRotationTranslator | ||||
|             session.setSpawned(false); | ||||
|         } | ||||
|  |  | |||
|  | @ -52,7 +52,7 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator<Serve | |||
| 
 | ||||
|             RespawnPacket respawnPacket = new RespawnPacket(); | ||||
|             respawnPacket.setRuntimeEntityId(0); | ||||
|             respawnPacket.setPosition(Vector3f.from(0, 32767, 0)); | ||||
|             respawnPacket.setPosition(Vector3f.ZERO); | ||||
|             respawnPacket.setSpawnState(RespawnPacket.State.SERVER_SEARCHING); | ||||
|             session.getUpstream().sendPacket(respawnPacket); | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,9 +3,10 @@ package org.geysermc.connector.utils; | |||
| import com.github.steveice10.mc.protocol.data.game.chunk.Chunk; | ||||
| import com.github.steveice10.mc.protocol.data.game.chunk.Column; | ||||
| import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; | ||||
| import com.github.steveice10.mc.protocol.data.game.world.block.BlockChangeRecord; | ||||
| import com.github.steveice10.mc.protocol.data.game.world.block.BlockState; | ||||
| import com.nukkitx.math.vector.Vector3i; | ||||
| import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket; | ||||
| import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket; | ||||
| import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; | ||||
| import org.geysermc.connector.network.session.GeyserSession; | ||||
| import org.geysermc.connector.network.translators.TranslatorsInit; | ||||
|  | @ -72,6 +73,27 @@ public class ChunkUtils { | |||
|         session.getUpstream().sendPacket(waterPacket); | ||||
|     } | ||||
| 
 | ||||
|     public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius) { | ||||
|         int chunkX = position.getX() >> 4; | ||||
|         int chunkZ = position.getZ() >> 4; | ||||
|         NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); | ||||
|         chunkPublisherUpdatePacket.setPosition(position); | ||||
|         chunkPublisherUpdatePacket.setRadius(radius << 4); | ||||
|         session.getUpstream().sendPacket(chunkPublisherUpdatePacket); | ||||
|         session.setLastChunkPosition(null); | ||||
|         for (int x = -radius; x < radius; x++) { | ||||
|             for (int z = -radius; z < radius; z++) { | ||||
|                 LevelChunkPacket data = new LevelChunkPacket(); | ||||
|                 data.setChunkX(chunkX + x); | ||||
|                 data.setChunkZ(chunkZ + z); | ||||
|                 data.setSubChunksLength(0); | ||||
|                 data.setData(TranslatorsInit.EMPTY_LEVEL_CHUNK_DATA); | ||||
|                 data.setCachingEnabled(false); | ||||
|                 session.getUpstream().sendPacket(data); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static final class ChunkData { | ||||
|         public ChunkSection[] sections; | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,24 +4,16 @@ import com.nukkitx.math.vector.Vector3i; | |||
| import com.nukkitx.protocol.bedrock.packet.*; | ||||
| import org.geysermc.connector.entity.Entity; | ||||
| import org.geysermc.connector.network.session.GeyserSession; | ||||
| import org.geysermc.connector.network.translators.TranslatorsInit; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| 
 | ||||
| public class DimensionUtils { | ||||
|     public static void switchDimension(GeyserSession session, int javaDimension, boolean fake) { | ||||
|     public static void switchDimension(GeyserSession session, int javaDimension) { | ||||
|         int bedrockDimension = javaToBedrock(javaDimension); | ||||
|         Entity player = session.getPlayerEntity(); | ||||
|         if (bedrockDimension == player.getDimension()) | ||||
|             return; | ||||
|         Vector3i pos = Vector3i.from(0, Short.MAX_VALUE, 0); | ||||
| 
 | ||||
|         Vector3i pos = Vector3i.from(0, 32767, 0); | ||||
| 
 | ||||
|         List<Entity> entities = new ArrayList<>(session.getEntityCache().getEntities().values()); | ||||
|         for (Entity entity : entities) { | ||||
|             session.getEntityCache().removeEntity(entity, false); | ||||
|         } | ||||
|         session.getEntityCache().removeAllEntities(); | ||||
| 
 | ||||
|         ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); | ||||
|         changeDimensionPacket.setDimension(bedrockDimension); | ||||
|  | @ -43,49 +35,7 @@ public class DimensionUtils { | |||
|         session.getUpstream().sendPacket(eventPacket); | ||||
| 
 | ||||
|         session.setSpawned(false); | ||||
|         session.setSwitchingDim(true); | ||||
| 
 | ||||
|         if (fake) { | ||||
|             try { | ||||
|                 Thread.sleep(250); | ||||
|             } catch (InterruptedException e) { | ||||
|                 Thread.currentThread().interrupt(); | ||||
|             } | ||||
|             sendEmptyChunks(session, pos.toInt()); | ||||
|             waitForAck(session); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static void waitForAck(GeyserSession session) { | ||||
|         synchronized (session.getDimensionLock()) { | ||||
|             try { | ||||
|                 while (session.isSwitchingDim()) | ||||
|                     session.getDimensionLock().wait(); | ||||
|             } catch (InterruptedException e) { | ||||
|                 Thread.currentThread().interrupt(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public static void sendEmptyChunks(GeyserSession session, Vector3i position) { | ||||
|         int chunkX = position.getX() >> 4; | ||||
|         int chunkZ = position.getZ() >> 4; | ||||
|         NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); | ||||
|         chunkPublisherUpdatePacket.setPosition(position); | ||||
|         chunkPublisherUpdatePacket.setRadius(session.getRenderDistance() << 4); | ||||
|         session.getUpstream().sendPacket(chunkPublisherUpdatePacket); | ||||
|         session.setLastChunkPosition(null); | ||||
|         for (int x = -5; x < 5; x++) { | ||||
|             for (int z = -5; z < 5; z++) { | ||||
|                 LevelChunkPacket data = new LevelChunkPacket(); | ||||
|                 data.setChunkX(chunkX + x); | ||||
|                 data.setChunkZ(chunkZ + z); | ||||
|                 data.setSubChunksLength(0); | ||||
|                 data.setData(TranslatorsInit.EMPTY_LEVEL_CHUNK_DATA); | ||||
|                 data.setCachingEnabled(false); | ||||
|                 session.getUpstream().sendPacket(data); | ||||
|             } | ||||
|         } | ||||
|         session.setSwitchingDimension(true); | ||||
|     } | ||||
| 
 | ||||
|     public static int javaToBedrock(int javaDimension) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue