diff --git a/README.md b/README.md
index 65a1261bd..a21a1b6c9 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Build Status](https://ci.opencollab.dev/job/Geyser/job/master/badge/icon)](https://ci.opencollab.dev/job/GeyserMC/job/Geyser/job/master/)
[![Discord](https://img.shields.io/discord/613163671870242838.svg?color=%237289da&label=discord)](http://discord.geysermc.org/)
-[![HitCount](http://hits.dwyl.io/Geyser/GeyserMC.svg)](http://hits.dwyl.io/Geyser/GeyserMC)
+[![HitCount](http://hits.dwyl.com/Geyser/GeyserMC.svg)](http://hits.dwyl.com/Geyser/GeyserMC)
[![Crowdin](https://badges.crowdin.net/geyser/localized.svg)](https://translate.geysermc.org/)
Geyser is a bridge between Minecraft: Bedrock Edition and Minecraft: Java Edition, closing the gap from those wanting to play true cross-platform.
diff --git a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
index 5e279c121..3cb95391d 100644
--- a/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
+++ b/connector/src/main/java/org/geysermc/connector/GeyserConnector.java
@@ -62,6 +62,7 @@ import org.geysermc.floodgate.crypto.AesCipher;
import org.geysermc.floodgate.crypto.AesKeyProducer;
import org.geysermc.floodgate.crypto.Base64Topping;
import org.geysermc.floodgate.crypto.FloodgateCipher;
+import org.jetbrains.annotations.Contract;
import javax.naming.directory.Attribute;
import javax.naming.directory.InitialDirContext;
@@ -372,9 +373,14 @@ public class GeyserConnector {
* @param uuid the uuid
* @return the player or null
if there is no player online with this UUID
*/
+ @Contract("null -> null")
public GeyserSession getPlayerByUuid(UUID uuid) {
+ if (uuid == null) {
+ return null;
+ }
+
for (GeyserSession session : players) {
- if (session.getPlayerEntity().getUuid().equals(uuid)) {
+ if (uuid.equals(session.getPlayerEntity().getUuid())) {
return session;
}
}
diff --git a/connector/src/main/java/org/geysermc/connector/entity/player/SkullPlayerEntity.java b/connector/src/main/java/org/geysermc/connector/entity/player/SkullPlayerEntity.java
index 97f6f15c6..3f8d9ea93 100644
--- a/connector/src/main/java/org/geysermc/connector/entity/player/SkullPlayerEntity.java
+++ b/connector/src/main/java/org/geysermc/connector/entity/player/SkullPlayerEntity.java
@@ -28,10 +28,14 @@ package org.geysermc.connector.entity.player;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i;
+import com.nukkitx.protocol.bedrock.data.PlayerPermission;
+import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
+import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket;
import lombok.Getter;
import lombok.Setter;
+import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
/**
@@ -61,6 +65,33 @@ public class SkullPlayerEntity extends PlayerEntity {
metadata.getFlags().setFlag(EntityFlag.INVISIBLE, true); // Until the skin is loaded
}
+ /**
+ * Overwritten so each entity doesn't check for a linked entity
+ */
+ @Override
+ public void spawnEntity(GeyserSession session) {
+ AddPlayerPacket addPlayerPacket = new AddPlayerPacket();
+ addPlayerPacket.setUuid(getUuid());
+ addPlayerPacket.setUsername(getUsername());
+ addPlayerPacket.setRuntimeEntityId(geyserId);
+ addPlayerPacket.setUniqueEntityId(geyserId);
+ addPlayerPacket.setPosition(position.clone().sub(0, EntityType.PLAYER.getOffset(), 0));
+ addPlayerPacket.setRotation(getBedrockRotation());
+ addPlayerPacket.setMotion(motion);
+ addPlayerPacket.setHand(hand);
+ addPlayerPacket.getAdventureSettings().setCommandPermission(CommandPermission.NORMAL);
+ addPlayerPacket.getAdventureSettings().setPlayerPermission(PlayerPermission.MEMBER);
+ addPlayerPacket.setDeviceId("");
+ addPlayerPacket.setPlatformChatId("");
+ addPlayerPacket.getMetadata().putAll(metadata);
+
+ valid = true;
+ session.sendUpstreamPacket(addPlayerPacket);
+
+ updateEquipment(session);
+ updateBedrockAttributes(session);
+ }
+
public void despawnEntity(GeyserSession session, Vector3i position) {
this.despawnEntity(session);
session.getSkullCache().remove(position, this);
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 253088bba..767a61acd 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
@@ -98,7 +98,6 @@ import org.geysermc.cumulus.util.FormBuilder;
import org.geysermc.floodgate.crypto.FloodgateCipher;
import org.geysermc.floodgate.util.BedrockData;
-import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.StandardCharsets;
@@ -672,7 +671,16 @@ public class GeyserSession implements CommandSender {
return;
}
connector.getLogger().info(LanguageUtils.getLocaleStringLog("geyser.network.remote.connect", authData.getName(), protocol.getProfile().getName(), remoteAddress));
- playerEntity.setUuid(protocol.getProfile().getId());
+ UUID uuid = protocol.getProfile().getId();
+ if (uuid == null) {
+ // Set what our UUID *probably* is going to be
+ if (remoteAuthType == AuthType.FLOODGATE) {
+ uuid = new UUID(0, Long.parseLong(authData.getXboxUUID()));
+ } else {
+ uuid = UUID.nameUUIDFromBytes(("OfflinePlayer:" + protocol.getProfile().getName()).getBytes(StandardCharsets.UTF_8));
+ }
+ }
+ playerEntity.setUuid(uuid);
playerEntity.setUsername(protocol.getProfile().getName());
String locale = clientData.getLanguageCode();
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 a2eb60053..4d6750bc0 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
@@ -59,6 +59,7 @@ public class EntityCache {
public EntityCache(GeyserSession session) {
this.session = session;
+ cachedPlayerEntityLinks.defaultReturnValue(-1L);
}
public void spawnEntity(Entity entity) {
@@ -100,6 +101,9 @@ public class EntityCache {
for (Entity entity : entities) {
session.getEntityCache().removeEntity(entity, false);
}
+
+ // As a precaution
+ cachedPlayerEntityLinks.clear();
}
public Entity getEntityByGeyserId(long geyserId) {
@@ -160,7 +164,7 @@ public class EntityCache {
}
public long getCachedPlayerEntityLink(long playerId) {
- return cachedPlayerEntityLinks.getOrDefault(playerId, -1);
+ return cachedPlayerEntityLinks.remove(playerId);
}
public void addCachedPlayerEntityLink(long playerId, long linkedEntityId) {
diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java
index b7d6c5e06..da9ce64ff 100644
--- a/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java
+++ b/connector/src/main/java/org/geysermc/connector/network/translators/java/entity/JavaEntitySetPassengersTranslator.java
@@ -47,9 +47,11 @@ public class JavaEntitySetPassengersTranslator extends PacketTranslator