Don't store GameProfile class of players

This stores repetitive information, and also we don't currently use the signature, so it's wasted memory.
This commit is contained in:
Camotoy 2022-03-30 22:30:49 -04:00
parent 7a5321b78f
commit 2a05dd57ff
No known key found for this signature in database
GPG Key ID: 7EEFB66FE798081F
10 changed files with 68 additions and 80 deletions

View File

@ -25,7 +25,6 @@
package org.geysermc.geyser.entity.type.player; package org.geysermc.geyser.entity.type.player;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata; import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
@ -61,15 +60,21 @@ import org.geysermc.geyser.translator.text.MessageTranslator;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.Collections; import java.util.Collections;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@Getter @Setter @Getter @Setter
public class PlayerEntity extends LivingEntity { public class PlayerEntity extends LivingEntity {
public static final float SNEAKING_POSE_HEIGHT = 1.5f; public static final float SNEAKING_POSE_HEIGHT = 1.5f;
private GameProfile profile;
private String username; private String username;
private boolean playerList = true; // Player is in the player list private boolean playerList = true; // Player is in the player list
/**
* The textures property from the GameProfile.
*/
@Nullable
private String texturesProperty;
private Vector3i bedPosition; private Vector3i bedPosition;
@ -82,11 +87,12 @@ public class PlayerEntity extends LivingEntity {
*/ */
private ParrotEntity rightParrot; private ParrotEntity rightParrot;
public PlayerEntity(GeyserSession session, int entityId, long geyserId, GameProfile gameProfile, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) { public PlayerEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position,
super(session, entityId, geyserId, gameProfile.getId(), EntityDefinitions.PLAYER, position, motion, yaw, pitch, headYaw); Vector3f motion, float yaw, float pitch, float headYaw, String username, @Nullable String texturesProperty) {
super(session, entityId, geyserId, uuid, EntityDefinitions.PLAYER, position, motion, yaw, pitch, headYaw);
profile = gameProfile; this.username = username;
username = gameProfile.getName(); this.texturesProperty = texturesProperty;
} }
@Override @Override

View File

@ -25,7 +25,6 @@
package org.geysermc.geyser.entity.type.player; package org.geysermc.geyser.entity.type.player;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute; import com.github.steveice10.mc.protocol.data.game.entity.attribute.Attribute;
import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType; import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeType;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose; import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
@ -71,7 +70,7 @@ public class SessionPlayerEntity extends PlayerEntity {
private int fakeTradeXp; private int fakeTradeXp;
public SessionPlayerEntity(GeyserSession session) { public SessionPlayerEntity(GeyserSession session) {
super(session, -1, 1, new GameProfile(UUID.randomUUID(), "unknown"), Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0); super(session, -1, 1, UUID.randomUUID(), Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, "unknown", null);
valid = true; valid = true;
} }

View File

@ -25,7 +25,6 @@
package org.geysermc.geyser.entity.type.player; package org.geysermc.geyser.entity.type.player;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.math.vector.Vector3i; import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.protocol.bedrock.data.PlayerPermission; import com.nukkitx.protocol.bedrock.data.PlayerPermission;
@ -36,6 +35,8 @@ import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket;
import lombok.Getter; import lombok.Getter;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import java.util.UUID;
/** /**
* A wrapper to handle skulls more effectively - skulls have to be treated as entities since there are no * A wrapper to handle skulls more effectively - skulls have to be treated as entities since there are no
* custom player skulls in Bedrock. * custom player skulls in Bedrock.
@ -48,8 +49,8 @@ public class SkullPlayerEntity extends PlayerEntity {
@Getter @Getter
private final int blockState; private final int blockState;
public SkullPlayerEntity(GeyserSession session, long geyserId, GameProfile gameProfile, Vector3f position, float rotation, int blockState) { public SkullPlayerEntity(GeyserSession session, long geyserId, Vector3f position, float rotation, int blockState, String texturesProperty) {
super(session, 0, geyserId, gameProfile, position, Vector3f.ZERO, rotation, 0, rotation); super(session, 0, geyserId, UUID.randomUUID(), position, Vector3f.ZERO, rotation, 0, rotation, "", texturesProperty);
this.blockState = blockState; this.blockState = blockState;
setPlayerList(false); setPlayerList(false);
} }

View File

@ -25,7 +25,6 @@
package org.geysermc.geyser.skin; package org.geysermc.geyser.skin;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
@ -106,7 +105,7 @@ public class FakeHeadProvider {
session.getPlayerWithCustomHeads().add(entity.getUuid()); session.getPlayerWithCustomHeads().add(entity.getUuid());
GameProfile.Property texturesProperty = entity.getProfile().getProperty("textures"); String texturesProperty = entity.getTexturesProperty();
SkinProvider.EXECUTOR_SERVICE.execute(() -> { SkinProvider.EXECUTOR_SERVICE.execute(() -> {
try { try {
@ -182,7 +181,7 @@ public class FakeHeadProvider {
@Getter @Getter
@Setter @Setter
private static class FakeHeadEntry { private static class FakeHeadEntry {
private final GameProfile.Property texturesProperty; private final String texturesProperty;
private final String fakeHeadSkinUrl; private final String fakeHeadSkinUrl;
private PlayerEntity entity; private PlayerEntity entity;
@ -192,18 +191,7 @@ public class FakeHeadProvider {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
FakeHeadEntry that = (FakeHeadEntry) o; FakeHeadEntry that = (FakeHeadEntry) o;
return equals(texturesProperty, that.texturesProperty) && Objects.equals(fakeHeadSkinUrl, that.fakeHeadSkinUrl); return Objects.equals(texturesProperty, that.texturesProperty) && Objects.equals(fakeHeadSkinUrl, that.fakeHeadSkinUrl);
}
private boolean equals(GameProfile.Property a, GameProfile.Property b) {
//TODO actually fix this in MCAuthLib
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
return Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getValue(), b.getValue()) && Objects.equals(a.getSignature(), b.getSignature());
} }
@Override @Override

View File

@ -26,7 +26,6 @@
package org.geysermc.geyser.skin; package org.geysermc.geyser.skin;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag; import com.github.steveice10.opennbt.tag.builtin.StringTag;
@ -34,9 +33,9 @@ import com.nukkitx.protocol.bedrock.data.skin.ImageData;
import com.nukkitx.protocol.bedrock.data.skin.SerializedSkin; import com.nukkitx.protocol.bedrock.data.skin.SerializedSkin;
import com.nukkitx.protocol.bedrock.packet.PlayerListPacket; import com.nukkitx.protocol.bedrock.packet.PlayerListPacket;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.session.auth.AuthType;
import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.entity.type.player.PlayerEntity;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.auth.AuthType;
import org.geysermc.geyser.session.auth.BedrockClientData; import org.geysermc.geyser.session.auth.BedrockClientData;
import org.geysermc.geyser.text.GeyserLocale; import org.geysermc.geyser.text.GeyserLocale;
@ -54,7 +53,7 @@ public class SkinManager {
* Builds a Bedrock player list entry from our existing, cached Bedrock skin information * Builds a Bedrock player list entry from our existing, cached Bedrock skin information
*/ */
public static PlayerListPacket.Entry buildCachedEntry(GeyserSession session, PlayerEntity playerEntity) { public static PlayerListPacket.Entry buildCachedEntry(GeyserSession session, PlayerEntity playerEntity) {
GameProfileData data = GameProfileData.from(playerEntity.getProfile()); GameProfileData data = GameProfileData.from(playerEntity);
SkinProvider.Cape cape = SkinProvider.getCachedCape(data.capeUrl()); SkinProvider.Cape cape = SkinProvider.getCachedCape(data.capeUrl());
SkinProvider.SkinGeometry geometry = SkinProvider.SkinGeometry.getLegacy(data.isAlex()); SkinProvider.SkinGeometry geometry = SkinProvider.SkinGeometry.getLegacy(data.isAlex());
@ -65,8 +64,8 @@ public class SkinManager {
return buildEntryManually( return buildEntryManually(
session, session,
playerEntity.getProfile().getId(), playerEntity.getUuid(),
playerEntity.getProfile().getName(), playerEntity.getUsername(),
playerEntity.getGeyserId(), playerEntity.getGeyserId(),
skin.getTextureUrl(), skin.getTextureUrl(),
skin.getSkinData(), skin.getSkinData(),
@ -227,31 +226,31 @@ public class SkinManager {
} }
/** /**
* Generate the GameProfileData from the given GameProfile * Generate the GameProfileData from the given player entity
* *
* @param profile GameProfile to build the GameProfileData from * @param entity entity to build the GameProfileData from
* @return The built GameProfileData * @return The built GameProfileData
*/ */
public static GameProfileData from(GameProfile profile) { public static GameProfileData from(PlayerEntity entity) {
try { try {
GameProfile.Property skinProperty = profile.getProperty("textures"); String texturesProperty = entity.getTexturesProperty();
if (skinProperty == null) { if (texturesProperty == null) {
// Likely offline mode // Likely offline mode
return loadBedrockOrOfflineSkin(profile); return loadBedrockOrOfflineSkin(entity);
} }
GameProfileData data = loadFromJson(skinProperty.getValue()); GameProfileData data = loadFromJson(texturesProperty);
if (data != null) { if (data != null) {
return data; return data;
} else { } else {
return loadBedrockOrOfflineSkin(profile); return loadBedrockOrOfflineSkin(entity);
} }
} catch (IOException exception) { } catch (IOException exception) {
GeyserImpl.getInstance().getLogger().debug("Something went wrong while processing skin for " + profile.getName()); GeyserImpl.getInstance().getLogger().debug("Something went wrong while processing skin for " + entity.getUsername());
if (GeyserImpl.getInstance().getConfig().isDebugMode()) { if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
exception.printStackTrace(); exception.printStackTrace();
} }
return loadBedrockOrOfflineSkin(profile); return loadBedrockOrOfflineSkin(entity);
} }
} }
@ -280,14 +279,15 @@ public class SkinManager {
* @return default skin with default cape when texture data is invalid, or the Bedrock player's skin if this * @return default skin with default cape when texture data is invalid, or the Bedrock player's skin if this
* is a Bedrock player. * is a Bedrock player.
*/ */
private static GameProfileData loadBedrockOrOfflineSkin(GameProfile profile) { private static GameProfileData loadBedrockOrOfflineSkin(PlayerEntity entity) {
// Fallback to the offline mode of working it out // Fallback to the offline mode of working it out
boolean isAlex = (Math.abs(profile.getId().hashCode() % 2) == 1); UUID uuid = entity.getUuid();
boolean isAlex = (Math.abs(uuid.hashCode() % 2) == 1);
String skinUrl = isAlex ? SkinProvider.EMPTY_SKIN_ALEX.getTextureUrl() : SkinProvider.EMPTY_SKIN.getTextureUrl(); String skinUrl = isAlex ? SkinProvider.EMPTY_SKIN_ALEX.getTextureUrl() : SkinProvider.EMPTY_SKIN.getTextureUrl();
String capeUrl = SkinProvider.EMPTY_CAPE.getTextureUrl(); String capeUrl = SkinProvider.EMPTY_CAPE.getTextureUrl();
if (("steve".equals(skinUrl) || "alex".equals(skinUrl)) && GeyserImpl.getInstance().getConfig().getRemote().getAuthType() != AuthType.ONLINE) { if (("steve".equals(skinUrl) || "alex".equals(skinUrl)) && GeyserImpl.getInstance().getConfig().getRemote().getAuthType() != AuthType.ONLINE) {
GeyserSession session = GeyserImpl.getInstance().connectionByUuid(profile.getId()); GeyserSession session = GeyserImpl.getInstance().connectionByUuid(uuid);
if (session != null) { if (session != null) {
skinUrl = session.getClientData().getSkinId(); skinUrl = session.getClientData().getSkinId();

View File

@ -27,7 +27,6 @@ package org.geysermc.geyser.skin;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.IntArrayTag; import com.github.steveice10.opennbt.tag.builtin.IntArrayTag;
import com.github.steveice10.opennbt.tag.builtin.Tag; import com.github.steveice10.opennbt.tag.builtin.Tag;
@ -53,7 +52,6 @@ import java.io.IOException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.Predicate; import java.util.function.Predicate;
@ -157,7 +155,7 @@ public class SkinProvider {
} }
public static CompletableFuture<SkinProvider.SkinData> requestSkinData(PlayerEntity entity) { public static CompletableFuture<SkinProvider.SkinData> requestSkinData(PlayerEntity entity) {
SkinManager.GameProfileData data = SkinManager.GameProfileData.from(entity.getProfile()); SkinManager.GameProfileData data = SkinManager.GameProfileData.from(entity);
return requestSkinAndCape(entity.getUuid(), data.skinUrl(), data.capeUrl()) return requestSkinAndCape(entity.getUuid(), data.skinUrl(), data.capeUrl())
.thenApplyAsync(skinAndCape -> { .thenApplyAsync(skinAndCape -> {
@ -546,12 +544,11 @@ public class SkinProvider {
* @param skullOwner the CompoundTag of the skull with no textures * @param skullOwner the CompoundTag of the skull with no textures
* @return a completable GameProfile with textures included * @return a completable GameProfile with textures included
*/ */
public static CompletableFuture<GameProfile> requestTexturesFromUsername(CompoundTag skullOwner) { public static CompletableFuture<String> requestTexturesFromUsername(CompoundTag skullOwner) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
Tag uuidTag = skullOwner.get("Id"); Tag uuidTag = skullOwner.get("Id");
String uuidToString = ""; String uuidToString = "";
JsonNode node; JsonNode node;
GameProfile gameProfile = new GameProfile(UUID.randomUUID(), "");
boolean retrieveUuidFromInternet = !(uuidTag instanceof IntArrayTag); // also covers null check boolean retrieveUuidFromInternet = !(uuidTag instanceof IntArrayTag); // also covers null check
if (!retrieveUuidFromInternet) { if (!retrieveUuidFromInternet) {
@ -577,15 +574,12 @@ public class SkinProvider {
// Get textures from UUID // Get textures from UUID
node = WebUtils.getJson("https://sessionserver.mojang.com/session/minecraft/profile/" + uuidToString); node = WebUtils.getJson("https://sessionserver.mojang.com/session/minecraft/profile/" + uuidToString);
List<GameProfile.Property> profileProperties = new ArrayList<>();
JsonNode properties = node.get("properties"); JsonNode properties = node.get("properties");
if (properties == null) { if (properties == null) {
GeyserImpl.getInstance().getLogger().debug("No properties found in Mojang response for " + uuidToString); GeyserImpl.getInstance().getLogger().debug("No properties found in Mojang response for " + uuidToString);
return null; return null;
} }
profileProperties.add(new GameProfile.Property("textures", node.get("properties").get(0).get("value").asText())); return node.get("properties").get(0).get("value").asText();
gameProfile.setProperties(profileProperties);
return gameProfile;
} catch (Exception e) { } catch (Exception e) {
if (GeyserImpl.getInstance().getConfig().isDebugMode()) { if (GeyserImpl.getInstance().getConfig().isDebugMode()) {
e.printStackTrace(); e.printStackTrace();

View File

@ -50,7 +50,7 @@ public class SkullSkinManager extends SkinManager {
public static void requestAndHandleSkin(PlayerEntity entity, GeyserSession session, public static void requestAndHandleSkin(PlayerEntity entity, GeyserSession session,
Consumer<SkinProvider.Skin> skinConsumer) { Consumer<SkinProvider.Skin> skinConsumer) {
GameProfileData data = GameProfileData.from(entity.getProfile()); GameProfileData data = GameProfileData.from(entity);
SkinProvider.requestSkin(entity.getUuid(), data.skinUrl(), true) SkinProvider.requestSkin(entity.getUuid(), data.skinUrl(), true)
.whenCompleteAsync((skin, throwable) -> { .whenCompleteAsync((skin, throwable) -> {

View File

@ -25,7 +25,6 @@
package org.geysermc.geyser.translator.level.block.entity; package org.geysermc.geyser.translator.level.block.entity;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType; import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag; import com.github.steveice10.opennbt.tag.builtin.ListTag;
@ -35,15 +34,12 @@ import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.NbtMapBuilder; import com.nukkitx.nbt.NbtMapBuilder;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.type.player.SkullPlayerEntity; import org.geysermc.geyser.entity.type.player.SkullPlayerEntity;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.level.block.BlockStateValues; import org.geysermc.geyser.level.block.BlockStateValues;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.skin.SkinProvider; import org.geysermc.geyser.skin.SkinProvider;
import org.geysermc.geyser.skin.SkullSkinManager; import org.geysermc.geyser.skin.SkullSkinManager;
import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -62,7 +58,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
builder.put("SkullType", skullVariant); builder.put("SkullType", skullVariant);
} }
public static CompletableFuture<GameProfile> getProfile(CompoundTag tag) { private static CompletableFuture<String> getTextures(CompoundTag tag) {
CompoundTag owner = tag.get("SkullOwner"); CompoundTag owner = tag.get("SkullOwner");
if (owner != null) { if (owner != null) {
CompoundTag properties = owner.get("Properties"); CompoundTag properties = owner.get("Properties");
@ -73,13 +69,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
ListTag textures = properties.get("textures"); ListTag textures = properties.get("textures");
LinkedHashMap<?,?> tag1 = (LinkedHashMap<?,?>) textures.get(0).getValue(); LinkedHashMap<?,?> tag1 = (LinkedHashMap<?,?>) textures.get(0).getValue();
StringTag texture = (StringTag) tag1.get("Value"); StringTag texture = (StringTag) tag1.get("Value");
return CompletableFuture.completedFuture(texture.getValue());
List<GameProfile.Property> profileProperties = new ArrayList<>();
GameProfile gameProfile = new GameProfile(UUID.randomUUID(), "");
profileProperties.add(new GameProfile.Property("textures", texture.getValue()));
gameProfile.setProperties(profileProperties);
return CompletableFuture.completedFuture(gameProfile);
} }
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
@ -108,21 +98,21 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
Vector3i blockPosition = Vector3i.from(posX, posY, posZ); Vector3i blockPosition = Vector3i.from(posX, posY, posZ);
Vector3f entityPosition = Vector3f.from(x, y, z); Vector3f entityPosition = Vector3f.from(x, y, z);
getProfile(tag).whenComplete((gameProfile, throwable) -> { getTextures(tag).whenComplete((texturesProperty, throwable) -> {
if (gameProfile == null) { if (texturesProperty == null) {
session.getGeyser().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag); session.getGeyser().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag);
return; return;
} }
if (session.getEventLoop().inEventLoop()) { if (session.getEventLoop().inEventLoop()) {
spawnPlayer(session, gameProfile, blockPosition, entityPosition, rotation, blockState); spawnPlayer(session, texturesProperty, blockPosition, entityPosition, rotation, blockState);
} else { } else {
session.executeInEventLoop(() -> spawnPlayer(session, gameProfile, blockPosition, entityPosition, rotation, blockState)); session.executeInEventLoop(() -> spawnPlayer(session, texturesProperty, blockPosition, entityPosition, rotation, blockState));
} }
}); });
} }
private static void spawnPlayer(GeyserSession session, GameProfile profile, Vector3i blockPosition, private static void spawnPlayer(GeyserSession session, String texturesProperty, Vector3i blockPosition,
Vector3f entityPosition, float rotation, int blockState) { Vector3f entityPosition, float rotation, int blockState) {
long geyserId = session.getEntityCache().getNextEntityId().incrementAndGet(); long geyserId = session.getEntityCache().getNextEntityId().incrementAndGet();
@ -132,7 +122,7 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
existingSkull.despawnEntity(blockPosition); existingSkull.despawnEntity(blockPosition);
} }
SkullPlayerEntity player = new SkullPlayerEntity(session, geyserId, profile, entityPosition, rotation, blockState); SkullPlayerEntity player = new SkullPlayerEntity(session, geyserId, entityPosition, rotation, blockState, texturesProperty);
// Cache entity // Cache entity
session.getSkullCache().put(blockPosition, player); session.getSkullCache().put(blockPosition, player);

View File

@ -25,6 +25,7 @@
package org.geysermc.geyser.translator.protocol.java.entity.player; package org.geysermc.geyser.translator.protocol.java.entity.player;
import com.github.steveice10.mc.auth.data.GameProfile;
import com.github.steveice10.mc.protocol.data.game.PlayerListEntry; import com.github.steveice10.mc.protocol.data.game.PlayerListEntry;
import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction; import com.github.steveice10.mc.protocol.data.game.PlayerListEntryAction;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerInfoPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundPlayerInfoPacket;
@ -50,31 +51,38 @@ public class JavaPlayerInfoTranslator extends PacketTranslator<ClientboundPlayer
for (PlayerListEntry entry : packet.getEntries()) { for (PlayerListEntry entry : packet.getEntries()) {
switch (packet.getAction()) { switch (packet.getAction()) {
case ADD_PLAYER -> { case ADD_PLAYER -> {
GameProfile profile = entry.getProfile();
PlayerEntity playerEntity; PlayerEntity playerEntity;
boolean self = entry.getProfile().getId().equals(session.getPlayerEntity().getUuid()); boolean self = profile.getId().equals(session.getPlayerEntity().getUuid());
if (self) { if (self) {
// Entity is ourself // Entity is ourself
playerEntity = session.getPlayerEntity(); playerEntity = session.getPlayerEntity();
} else { } else {
playerEntity = session.getEntityCache().getPlayerEntity(entry.getProfile().getId()); playerEntity = session.getEntityCache().getPlayerEntity(profile.getId());
} }
GameProfile.Property textures = profile.getProperty("textures");
String texturesProperty = textures == null ? null : textures.getValue();
if (playerEntity == null) { if (playerEntity == null) {
// It's a new player // It's a new player
playerEntity = new PlayerEntity( playerEntity = new PlayerEntity(
session, session,
-1, -1,
session.getEntityCache().getNextEntityId().incrementAndGet(), session.getEntityCache().getNextEntityId().incrementAndGet(),
entry.getProfile(), profile.getId(),
Vector3f.ZERO, Vector3f.ZERO,
Vector3f.ZERO, Vector3f.ZERO,
0, 0, 0 0, 0, 0,
profile.getName(),
texturesProperty
); );
session.getEntityCache().addPlayerEntity(playerEntity); session.getEntityCache().addPlayerEntity(playerEntity);
} else { } else {
playerEntity.setProfile(entry.getProfile()); playerEntity.setUsername(profile.getName());
playerEntity.setTexturesProperty(texturesProperty);
} }
playerEntity.setPlayerList(true); playerEntity.setPlayerList(true);

View File

@ -48,7 +48,9 @@ public class JavaAddPlayerTranslator extends PacketTranslator<ClientboundAddPlay
PlayerEntity entity; PlayerEntity entity;
if (packet.getUuid().equals(session.getPlayerEntity().getUuid())) { if (packet.getUuid().equals(session.getPlayerEntity().getUuid())) {
// Server is sending a fake version of the current player // Server is sending a fake version of the current player
entity = new PlayerEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), session.getPlayerEntity().getProfile(), position, Vector3f.ZERO, yaw, pitch, headYaw); entity = new PlayerEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(),
session.getPlayerEntity().getUuid(), position, Vector3f.ZERO, yaw, pitch, headYaw, session.getPlayerEntity().getUsername(),
session.getPlayerEntity().getTexturesProperty());
} else { } else {
entity = session.getEntityCache().getPlayerEntity(packet.getUuid()); entity = session.getEntityCache().getPlayerEntity(packet.getUuid());
if (entity == null) { if (entity == null) {