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.inventory.PlayerInventory; | ||||||
| import org.geysermc.connector.network.session.cache.*; | import org.geysermc.connector.network.session.cache.*; | ||||||
| import org.geysermc.connector.network.translators.Registry; | import org.geysermc.connector.network.translators.Registry; | ||||||
| import org.geysermc.connector.network.translators.TranslatorsInit; | import org.geysermc.connector.utils.ChunkUtils; | ||||||
| import org.geysermc.connector.utils.DimensionUtils; |  | ||||||
| import org.geysermc.connector.utils.Toolbox; | import org.geysermc.connector.utils.Toolbox; | ||||||
| 
 | 
 | ||||||
| import java.net.InetSocketAddress; | import java.net.InetSocketAddress; | ||||||
|  | @ -100,8 +99,8 @@ public class GeyserSession implements Player { | ||||||
|     private GameMode gameMode = GameMode.SURVIVAL; |     private GameMode gameMode = GameMode.SURVIVAL; | ||||||
| 
 | 
 | ||||||
|     @Setter |     @Setter | ||||||
|     private volatile boolean switchingDim = false; |     private boolean switchingDimension = false; | ||||||
|     private final Object dimensionLock = new Object(); |     private boolean manyDimPackets = false; | ||||||
|     private ServerRespawnPacket lastDimPacket = null; |     private ServerRespawnPacket lastDimPacket = null; | ||||||
| 
 | 
 | ||||||
|     public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { |     public GeyserSession(GeyserConnector connector, BedrockServerSession bedrockServerSession) { | ||||||
|  | @ -128,25 +127,8 @@ public class GeyserSession implements Player { | ||||||
|     public void connect(RemoteServer remoteServer) { |     public void connect(RemoteServer remoteServer) { | ||||||
|         startGame(); |         startGame(); | ||||||
|         this.remoteServer = remoteServer; |         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; |         ChunkUtils.sendEmptyChunks(this, playerEntity.getPosition().toInt(), 5); | ||||||
|         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); |  | ||||||
| 
 | 
 | ||||||
|         BiomeDefinitionListPacket biomePacket = new BiomeDefinitionListPacket(); |         BiomeDefinitionListPacket biomePacket = new BiomeDefinitionListPacket(); | ||||||
|         biomePacket.setTag(CompoundTag.EMPTY); |         biomePacket.setTag(CompoundTag.EMPTY); | ||||||
|  | @ -207,9 +189,7 @@ public class GeyserSession implements Player { | ||||||
|                         if (!closed) { |                         if (!closed) { | ||||||
|                             //handle consecutive respawn packets |                             //handle consecutive respawn packets | ||||||
|                             if (event.getPacket().getClass().equals(ServerRespawnPacket.class)) { |                             if (event.getPacket().getClass().equals(ServerRespawnPacket.class)) { | ||||||
|                                 if (lastDimPacket != null) { |                                 manyDimPackets = lastDimPacket != null; | ||||||
|                                     DimensionUtils.switchDimension(GeyserSession.this, lastDimPacket.getDimension(), true); |  | ||||||
|                                 } |  | ||||||
|                                 lastDimPacket = event.getPacket(); |                                 lastDimPacket = event.getPacket(); | ||||||
|                                 return; |                                 return; | ||||||
|                             } else if (lastDimPacket != null) { |                             } else if (lastDimPacket != null) { | ||||||
|  |  | ||||||
|  | @ -73,6 +73,13 @@ public class EntityCache { | ||||||
|         return false; |         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) { |     public Entity getEntityByGeyserId(long geyserId) { | ||||||
|         return entities.get(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.ClientPlayerPlaceBlockPacket; | ||||||
| import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket; | import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerStatePacket; | ||||||
| import com.nukkitx.math.vector.Vector3i; | 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.PlayerActionPacket; | ||||||
| import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; |  | ||||||
| import org.geysermc.connector.entity.Entity; | 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; | ||||||
|  | @ -108,10 +106,7 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket | ||||||
|                 // Handled in BedrockInventoryTransactionTranslator |                 // Handled in BedrockInventoryTransactionTranslator | ||||||
|                 break; |                 break; | ||||||
|             case DIMENSION_CHANGE_SUCCESS: |             case DIMENSION_CHANGE_SUCCESS: | ||||||
|                 synchronized (session.getDimensionLock()) { |                 session.setSwitchingDimension(false); | ||||||
|                     session.setSwitchingDim(false); |  | ||||||
|                     session.getDimensionLock().notifyAll(); |  | ||||||
|                 } |  | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -42,7 +42,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 (entity == null || !session.isSpawned() || session.isSwitchingDim()) return; |         if (entity == null || !session.isSpawned() || session.isSwitchingDimension()) return; | ||||||
| 
 | 
 | ||||||
|         if (!session.getUpstream().isInitialized()) { |         if (!session.getUpstream().isInitialized()) { | ||||||
|             MoveEntityAbsolutePacket moveEntityBack = new MoveEntityAbsolutePacket(); |             MoveEntityAbsolutePacket moveEntityBack = new MoveEntityAbsolutePacket(); | ||||||
|  |  | ||||||
|  | @ -13,6 +13,11 @@ public class BedrockPlayerInitializedTranslator extends PacketTranslator<SetLoca | ||||||
|             if (!session.getUpstream().isInitialized()) { |             if (!session.getUpstream().isInitialized()) { | ||||||
|                 session.getUpstream().setInitialized(true); |                 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)) { |                 for (PlayerEntity entity : session.getEntityCache().getEntitiesByType(PlayerEntity.class)) { | ||||||
|                     if (!entity.isValid()) { |                     if (!entity.isValid()) { | ||||||
|                         // async skin loading |                         // 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(); |         PlayerEntity entity = session.getPlayerEntity(); | ||||||
|         entity.setEntityId(packet.getEntityId()); |         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(); |         AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket(); | ||||||
|         bedrockPacket.setUniqueEntityId(session.getPlayerEntity().getGeyserId()); |         bedrockPacket.setUniqueEntityId(session.getPlayerEntity().getGeyserId()); | ||||||
|         bedrockPacket.setPlayerPermission(1); |         bedrockPacket.setPlayerPermission(1); | ||||||
|  | @ -74,5 +65,9 @@ public class JavaJoinGameTranslator extends PacketTranslator<ServerJoinGamePacke | ||||||
|         ChunkRadiusUpdatedPacket chunkRadiusPacket = new ChunkRadiusUpdatedPacket(); |         ChunkRadiusUpdatedPacket chunkRadiusPacket = new ChunkRadiusUpdatedPacket(); | ||||||
|         chunkRadiusPacket.setRadius(session.getRenderDistance()); |         chunkRadiusPacket.setRadius(session.getRenderDistance()); | ||||||
|         session.getUpstream().sendPacket(chunkRadiusPacket); |         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()); |         session.setGameMode(packet.getGamemode()); | ||||||
| 
 | 
 | ||||||
|         if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { |         if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { | ||||||
|             DimensionUtils.switchDimension(session, packet.getDimension(), false); |             DimensionUtils.switchDimension(session, packet.getDimension()); | ||||||
|         } else { |         } else { | ||||||
|  |             if (session.isManyDimPackets()) { //reloading world | ||||||
|  |                 session.getEntityCache().removeAllEntities(); | ||||||
|  |                 //TODO: fix lighting bug | ||||||
|  |             } | ||||||
|             // Handled in JavaPlayerPositionRotationTranslator |             // Handled in JavaPlayerPositionRotationTranslator | ||||||
|             session.setSpawned(false); |             session.setSpawned(false); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -52,7 +52,7 @@ public class JavaPlayerPositionRotationTranslator extends PacketTranslator<Serve | ||||||
| 
 | 
 | ||||||
|             RespawnPacket respawnPacket = new RespawnPacket(); |             RespawnPacket respawnPacket = new RespawnPacket(); | ||||||
|             respawnPacket.setRuntimeEntityId(0); |             respawnPacket.setRuntimeEntityId(0); | ||||||
|             respawnPacket.setPosition(Vector3f.from(0, 32767, 0)); |             respawnPacket.setPosition(Vector3f.ZERO); | ||||||
|             respawnPacket.setSpawnState(RespawnPacket.State.SERVER_SEARCHING); |             respawnPacket.setSpawnState(RespawnPacket.State.SERVER_SEARCHING); | ||||||
|             session.getUpstream().sendPacket(respawnPacket); |             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.Chunk; | ||||||
| import com.github.steveice10.mc.protocol.data.game.chunk.Column; | 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.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.github.steveice10.mc.protocol.data.game.world.block.BlockState; | ||||||
| import com.nukkitx.math.vector.Vector3i; | 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 com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket; | ||||||
| import org.geysermc.connector.network.session.GeyserSession; | import org.geysermc.connector.network.session.GeyserSession; | ||||||
| import org.geysermc.connector.network.translators.TranslatorsInit; | import org.geysermc.connector.network.translators.TranslatorsInit; | ||||||
|  | @ -72,6 +73,27 @@ public class ChunkUtils { | ||||||
|         session.getUpstream().sendPacket(waterPacket); |         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 static final class ChunkData { | ||||||
|         public ChunkSection[] sections; |         public ChunkSection[] sections; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -4,24 +4,16 @@ import com.nukkitx.math.vector.Vector3i; | ||||||
| import com.nukkitx.protocol.bedrock.packet.*; | import com.nukkitx.protocol.bedrock.packet.*; | ||||||
| import org.geysermc.connector.entity.Entity; | 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.TranslatorsInit; |  | ||||||
| 
 |  | ||||||
| import java.util.ArrayList; |  | ||||||
| import java.util.List; |  | ||||||
| 
 | 
 | ||||||
| public class DimensionUtils { | 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); |         int bedrockDimension = javaToBedrock(javaDimension); | ||||||
|         Entity player = session.getPlayerEntity(); |         Entity player = session.getPlayerEntity(); | ||||||
|         if (bedrockDimension == player.getDimension()) |         if (bedrockDimension == player.getDimension()) | ||||||
|             return; |             return; | ||||||
|  |         Vector3i pos = Vector3i.from(0, Short.MAX_VALUE, 0); | ||||||
| 
 | 
 | ||||||
|         Vector3i pos = Vector3i.from(0, 32767, 0); |         session.getEntityCache().removeAllEntities(); | ||||||
| 
 |  | ||||||
|         List<Entity> entities = new ArrayList<>(session.getEntityCache().getEntities().values()); |  | ||||||
|         for (Entity entity : entities) { |  | ||||||
|             session.getEntityCache().removeEntity(entity, false); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); |         ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); | ||||||
|         changeDimensionPacket.setDimension(bedrockDimension); |         changeDimensionPacket.setDimension(bedrockDimension); | ||||||
|  | @ -43,49 +35,7 @@ public class DimensionUtils { | ||||||
|         session.getUpstream().sendPacket(eventPacket); |         session.getUpstream().sendPacket(eventPacket); | ||||||
| 
 | 
 | ||||||
|         session.setSpawned(false); |         session.setSpawned(false); | ||||||
|         session.setSwitchingDim(true); |         session.setSwitchingDimension(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); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static int javaToBedrock(int javaDimension) { |     public static int javaToBedrock(int javaDimension) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue