diff --git a/README.md b/README.md index 0108781c..005aa4a0 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,8 @@ Please note, Geyser is **not** (currently) a plugin. Watch the video below or ta ## Compiling 1. Clone the repo to your computer 2. [Install Maven](https://maven.apache.org/install.html) -3. Navigate to the Geyser root directory and run `mvn clean install` +3. Navigate to the Geyser root directory and run `git submodule update --init --recursive`. This downloads all the needed submodules for Geyser and is a crucial step in this process. +4. Run `mvn clean install` and locate to the `target` folder. ## Contributing Any contributions are appreciated. Please feel free to reach out to us on [Discord](http://discord.geysermc.org/) if diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java index 7feaacba..89de32d6 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/AgeableEntity.java @@ -28,6 +28,7 @@ package org.geysermc.connector.entity.living; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; import com.nukkitx.protocol.bedrock.data.EntityFlag; import org.geysermc.connector.entity.type.EntityType; import org.geysermc.connector.network.session.GeyserSession; @@ -41,7 +42,11 @@ public class AgeableEntity extends CreatureEntity { @Override public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { if (entityMetadata.getId() == 15) { - metadata.getFlags().setFlag(EntityFlag.BABY, (boolean) entityMetadata.getValue()); + boolean isBaby = (boolean) entityMetadata.getValue(); + if (isBaby) { + metadata.put(EntityData.SCALE, .55f); + metadata.getFlags().setFlag(EntityFlag.BABY, true); + } } super.updateBedrockMetadata(entityMetadata, session); diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java new file mode 100644 index 00000000..5829cc32 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/ArmorStandEntity.java @@ -0,0 +1,29 @@ +package org.geysermc.connector.entity.living; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityFlag; +import org.geysermc.connector.entity.LivingEntity; +import org.geysermc.connector.entity.living.MonsterEntity; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class ArmorStandEntity extends LivingEntity { + + public ArmorStandEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getType() == MetadataType.BYTE) { + byte xd = (byte) entityMetadata.getValue(); + if((xd & 0x01) == 0x01) { + metadata.put(EntityData.SCALE, .55f); + } + } + super.updateBedrockMetadata(entityMetadata, session); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/RabbitEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/RabbitEntity.java new file mode 100644 index 00000000..093d3c13 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/entity/living/RabbitEntity.java @@ -0,0 +1,27 @@ +package org.geysermc.connector.entity.living; + +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityFlag; +import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; + +public class RabbitEntity extends AnimalEntity { + public RabbitEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { + super(entityId, geyserId, entityType, position, motion, rotation); + } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + super.updateBedrockMetadata(entityMetadata, session); + if (entityMetadata.getId() == 15) { + metadata.put(EntityData.SCALE, .55f); + boolean isBaby = (boolean) entityMetadata.getValue(); + if(isBaby) { + metadata.put(EntityData.SCALE, .35f); + metadata.getFlags().setFlag(EntityFlag.BABY, true); + } + } + } +} \ No newline at end of file diff --git a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieEntity.java b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieEntity.java index 162c2272..c0d2c239 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieEntity.java +++ b/connector/src/main/java/org/geysermc/connector/entity/living/monster/ZombieEntity.java @@ -25,13 +25,29 @@ package org.geysermc.connector.entity.living.monster; +import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.data.EntityFlag; import org.geysermc.connector.entity.living.MonsterEntity; import org.geysermc.connector.entity.type.EntityType; +import org.geysermc.connector.network.session.GeyserSession; public class ZombieEntity extends MonsterEntity { public ZombieEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) { super(entityId, geyserId, entityType, position, motion, rotation); } + + @Override + public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) { + if (entityMetadata.getId() == 15) { + boolean isBaby = (boolean) entityMetadata.getValue(); + if (isBaby) { + metadata.put(EntityData.SCALE, .55f); + metadata.getFlags().setFlag(EntityFlag.BABY, true); + } + } + super.updateBedrockMetadata(entityMetadata, session); + } } diff --git a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java index 1179617d..f7a4b843 100644 --- a/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java +++ b/connector/src/main/java/org/geysermc/connector/entity/type/EntityType.java @@ -44,7 +44,7 @@ public enum EntityType { VILLAGER(AbstractMerchantEntity.class, 15, 1.8f, 0.6f, 0.6f, 1.62f), MOOSHROOM(AnimalEntity.class, 16, 1.4f, 0.9f), SQUID(WaterEntity.class, 17, 0.8f), - RABBIT(AnimalEntity.class, 18, 0.5f, 0.4f), + RABBIT(RabbitEntity.class, 18, 0.5f, 0.4f), BAT(AmbientEntity.class, 19, 0.9f, 0.5f), IRON_GOLEM(GolemEntity.class, 20, 2.7f, 1.4f), SNOW_GOLEM(GolemEntity.class, 21, 1.9f, 0.7f), @@ -90,7 +90,7 @@ public enum EntityType { PHANTOM(FlyingEntity.class, 58, 0.5f, 0.9f, 0.9f, 0.6f), RAVAGER(RaidParticipantEntity.class, 59, 1.9f, 1.2f), - ARMOR_STAND(LivingEntity.class, 61, 0f), + ARMOR_STAND(ArmorStandEntity.class, 61, 0f), TRIPOD_CAMERA(Entity.class, 62, 0f), PLAYER(PlayerEntity.class, 63, 1.8f, 0.6f, 0.6f, 1.62f), ITEM(ItemEntity.class, 64, 0.25f, 0.25f), diff --git a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java index 62b96473..cb50cc18 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/GeyserSession.java @@ -29,6 +29,7 @@ import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.protocol.MinecraftProtocol; import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode; +import com.github.steveice10.mc.protocol.packet.ingame.server.ServerRespawnPacket; import com.github.steveice10.packetlib.Client; import com.github.steveice10.packetlib.event.session.ConnectedEvent; import com.github.steveice10.packetlib.event.session.DisconnectedEvent; @@ -57,7 +58,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.ChunkUtils; import org.geysermc.connector.utils.Toolbox; import java.net.InetSocketAddress; @@ -98,6 +99,11 @@ public class GeyserSession implements Player { @Setter private GameMode gameMode = GameMode.SURVIVAL; + @Setter + private boolean switchingDimension = false; + private boolean manyDimPackets = false; + private ServerRespawnPacket lastDimPacket = null; + @Setter private int craftSlot = 0; @@ -125,25 +131,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(), 0, false); BiomeDefinitionListPacket biomePacket = new BiomeDefinitionListPacket(); biomePacket.setTag(CompoundTag.EMPTY); @@ -207,6 +196,16 @@ public class GeyserSession implements Player { @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) { + Registry.JAVA.translate(lastDimPacket.getClass(), lastDimPacket, GeyserSession.this); + lastDimPacket = null; + } + Registry.JAVA.translate(event.getPacket().getClass(), event.getPacket(), GeyserSession.this); } } diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java index fd0bd7c5..5e9ae0f0 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java @@ -25,10 +25,7 @@ package org.geysermc.connector.network.session.cache; -import it.unimi.dsi.fastutil.longs.Long2LongMap; -import it.unimi.dsi.fastutil.longs.Long2LongOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.longs.*; import lombok.Getter; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.PlayerEntity; @@ -45,9 +42,9 @@ public class EntityCache { private GeyserSession session; @Getter - private Long2ObjectMap entities = new Long2ObjectOpenHashMap<>(); - private Long2LongMap entityIdTranslations = new Long2LongOpenHashMap(); - private Map playerEntities = new HashMap<>(); + private Long2ObjectMap entities = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>()); + private Long2LongMap entityIdTranslations = Long2LongMaps.synchronize(new Long2LongOpenHashMap()); + private Map playerEntities = Collections.synchronizedMap(new HashMap<>()); private Map bossbars = new HashMap<>(); @Getter @@ -76,6 +73,13 @@ public class EntityCache { return false; } + public void removeAllEntities() { + List 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); } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java index 31559d96..59be2b23 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/TranslatorsInit.java @@ -158,6 +158,8 @@ public class TranslatorsInit { Registry.registerBedrock(InteractPacket.class, new BedrockInteractTranslator()); Registry.registerBedrock(TextPacket.class, new BedrockTextTranslator()); Registry.registerBedrock(ContainerClosePacket.class, new BedrockContainerCloseTranslator()); + Registry.registerBedrock(RespawnPacket.class, new BedrockRespawnTranslator()); + Registry.registerBedrock(ShowCreditsPacket.class, new BedrockShowCreditsTranslator()); itemTranslator = new ItemTranslator(); blockTranslator = new BlockTranslator(); diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 33467934..595ca862 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -34,6 +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.PlayStatusPacket; import com.nukkitx.protocol.bedrock.packet.PlayerActionPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.network.session.GeyserSession; @@ -53,7 +54,7 @@ public class BedrockActionTranslator extends PacketTranslator { + + @Override + public void translate(RespawnPacket packet, GeyserSession session) { + if (packet.getSpawnState() == RespawnPacket.State.CLIENT_READY) { + RespawnPacket respawnPacket = new RespawnPacket(); + respawnPacket.setRuntimeEntityId(0); + respawnPacket.setPosition(Vector3f.ZERO); + respawnPacket.setSpawnState(RespawnPacket.State.SERVER_SEARCHING); + session.getUpstream().sendPacket(respawnPacket); + + ClientRequestPacket javaRespawnPacket = new ClientRequestPacket(ClientRequest.RESPAWN); + session.getDownstream().getSession().send(javaRespawnPacket); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockShowCreditsTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockShowCreditsTranslator.java new file mode 100644 index 00000000..1d6844e9 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockShowCreditsTranslator.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 GeyserMC. http://geysermc.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @author GeyserMC + * @link https://github.com/GeyserMC/Geyser + */ + +package org.geysermc.connector.network.translators.bedrock; + +import com.github.steveice10.mc.protocol.data.game.ClientRequest; +import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket; +import com.nukkitx.protocol.bedrock.packet.ShowCreditsPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.network.translators.PacketTranslator; + +public class BedrockShowCreditsTranslator extends PacketTranslator { + + @Override + public void translate(ShowCreditsPacket packet, GeyserSession session) { + if (packet.getStatus() == ShowCreditsPacket.Status.END_CREDITS) { + ClientRequestPacket javaRespawnPacket = new ClientRequestPacket(ClientRequest.RESPAWN); + session.getDownstream().getSession().send(javaRespawnPacket); + } + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java index 87bb62e0..3cdc149d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/JavaJoinGameTranslator.java @@ -26,22 +26,20 @@ package org.geysermc.connector.network.translators.java; import com.github.steveice10.mc.protocol.packet.ingame.server.ServerJoinGamePacket; -import com.nukkitx.math.vector.Vector3i; -import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket; -import com.nukkitx.protocol.bedrock.packet.ChunkRadiusUpdatedPacket; -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; -import org.geysermc.connector.world.chunk.ChunkPosition; +import org.geysermc.connector.utils.DimensionUtils; public class JavaJoinGameTranslator extends PacketTranslator { @Override public void translate(ServerJoinGamePacket packet, GeyserSession session) { + PlayerEntity entity = session.getPlayerEntity(); + entity.setEntityId(packet.getEntityId()); + AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket(); bedrockPacket.setUniqueEntityId(session.getPlayerEntity().getGeyserId()); bedrockPacket.setPlayerPermission(1); @@ -51,9 +49,6 @@ public class JavaJoinGameTranslator extends PacketTranslator { @@ -41,39 +41,27 @@ public class JavaRespawnTranslator extends PacketTranslator if (entity == null) return; - if (entity.getDimension() == getDimension(packet.getDimension())) - 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 + entity.getAttributes().put(AttributeType.HEALTH, AttributeType.HEALTH.getAttribute(maxHealth, (maxHealth % 2 == 1 ? maxHealth + 1 : maxHealth))); session.getInventoryCache().setOpenInventory(null); - session.getChunkCache().getChunks().clear(); - entity.setDimension(getDimension(packet.getDimension())); - - ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); - changeDimensionPacket.setDimension(getDimension(packet.getDimension())); - changeDimensionPacket.setRespawn(false); - changeDimensionPacket.setPosition(entity.getPosition()); - session.getUpstream().sendPacket(changeDimensionPacket); SetPlayerGameTypePacket playerGameTypePacket = new SetPlayerGameTypePacket(); playerGameTypePacket.setGamemode(packet.getGamemode().ordinal()); session.getUpstream().sendPacket(playerGameTypePacket); session.setGameMode(packet.getGamemode()); - /* - PlayStatusPacket playStatusPacket = new PlayStatusPacket(); - playStatusPacket.setStatus(PlayStatusPacket.Status.PLAYER_SPAWN); - session.getUpstream().sendPacket(playStatusPacket); - */ - } - - private int getDimension(int javaDimension) { - switch (javaDimension) { - case -1: - return 1; - case 1: - return 2; + if (entity.getDimension() != DimensionUtils.javaToBedrock(packet.getDimension())) { + DimensionUtils.switchDimension(session, packet.getDimension(), false); + } else { + // Handled in JavaPlayerPositionRotationTranslator + session.setSpawned(false); + if (session.isManyDimPackets()) { //reloading world + int fakeDim = entity.getDimension() == 0 ? -1 : 0; + DimensionUtils.switchDimension(session, fakeDim, true); + DimensionUtils.switchDimension(session, packet.getDimension(), false); + } } - - return javaDimension; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java index 73376385..bebd8f9d 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/player/JavaPlayerHealthTranslator.java @@ -25,11 +25,7 @@ package org.geysermc.connector.network.translators.java.entity.player; -import com.github.steveice10.mc.protocol.data.game.ClientRequest; -import com.github.steveice10.mc.protocol.packet.ingame.client.ClientRequestPacket; import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerHealthPacket; -import com.nukkitx.math.vector.Vector3f; -import com.nukkitx.protocol.bedrock.packet.RespawnPacket; import com.nukkitx.protocol.bedrock.packet.SetHealthPacket; import org.geysermc.connector.entity.Entity; import org.geysermc.connector.entity.attribute.AttributeType; @@ -44,8 +40,9 @@ public class JavaPlayerHealthTranslator extends PacketTranslator> 4; + int chunkZ = position.getZ() >> 4; + NetworkChunkPublisherUpdatePacket chunkPublisherUpdatePacket = new NetworkChunkPublisherUpdatePacket(); + chunkPublisherUpdatePacket.setPosition(position); + chunkPublisherUpdatePacket.setRadius(radius + 1 << 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); + + if (forceUpdate) { + Vector3i pos = Vector3i.from(chunkX + x << 4, 80, chunkZ + z << 4); + UpdateBlockPacket blockPacket = new UpdateBlockPacket(); + blockPacket.setBlockPosition(pos); + blockPacket.setDataLayer(1); + blockPacket.setRuntimeId(1); + session.getUpstream().sendPacket(blockPacket); + } + } + } + } + public static final class ChunkData { public ChunkSection[] sections; diff --git a/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java new file mode 100644 index 00000000..ace1c682 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/utils/DimensionUtils.java @@ -0,0 +1,49 @@ +package org.geysermc.connector.utils; + +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; + +public class DimensionUtils { + public static void switchDimension(GeyserSession session, int javaDimension, boolean fake) { + int bedrockDimension = javaToBedrock(javaDimension); + Entity player = session.getPlayerEntity(); + if (bedrockDimension == player.getDimension()) + return; + Vector3i pos = Vector3i.from(0, Short.MAX_VALUE, 0); + + session.getEntityCache().removeAllEntities(); + + ChangeDimensionPacket changeDimensionPacket = new ChangeDimensionPacket(); + changeDimensionPacket.setDimension(bedrockDimension); + changeDimensionPacket.setRespawn(true); + changeDimensionPacket.setPosition(pos.toFloat()); + session.getUpstream().sendPacket(changeDimensionPacket); + player.setDimension(bedrockDimension); + + //let java server handle portal travel sound + StopSoundPacket stopSoundPacket = new StopSoundPacket(); + stopSoundPacket.setStoppingAllSound(true); + stopSoundPacket.setSoundName(""); + session.getUpstream().sendPacket(stopSoundPacket); + + if (fake) { + ChunkUtils.sendEmptyChunks(session, pos, 2, true); + } + + session.setSpawned(false); + session.setSwitchingDimension(true); + } + + public static int javaToBedrock(int javaDimension) { + switch (javaDimension) { + case -1: + return 1; + case 1: + return 2; + default: + return javaDimension; + } + } +}