Fix custom skulls 1.20.5

Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com>
This commit is contained in:
Joshua Castle 2024-04-24 18:13:07 -07:00
parent 9d540fe672
commit 652f6af784
No known key found for this signature in database
GPG key ID: 7ECA1A2FC38ABA9F
3 changed files with 17 additions and 20 deletions

View file

@ -66,8 +66,8 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
} }
} }
private static UUID getUUID(CompoundTag owner) { private static UUID getUUID(CompoundTag profile) {
if (owner.get("Id") instanceof IntArrayTag uuidTag && uuidTag.length() == 4) { if (profile.get("id") instanceof IntArrayTag uuidTag && uuidTag.length() == 4) {
int[] uuidAsArray = uuidTag.getValue(); int[] uuidAsArray = uuidTag.getValue();
// thank u viaversion // thank u viaversion
return new UUID((long) uuidAsArray[0] << 32 | ((long) uuidAsArray[1] & 0xFFFFFFFFL), return new UUID((long) uuidAsArray[0] << 32 | ((long) uuidAsArray[1] & 0xFFFFFFFFL),
@ -75,46 +75,44 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
} }
// Convert username to an offline UUID // Convert username to an offline UUID
String username = null; String username = null;
if (owner.get("Name") instanceof StringTag nameTag) { if (profile.get("name") instanceof StringTag nameTag) {
username = nameTag.getValue().toLowerCase(Locale.ROOT); username = nameTag.getValue().toLowerCase(Locale.ROOT);
} }
return UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8)); return UUID.nameUUIDFromBytes(("OfflinePlayer:" + username).getBytes(StandardCharsets.UTF_8));
} }
private static CompletableFuture<String> getTextures(CompoundTag owner, UUID uuid) { private static CompletableFuture<String> getTextures(CompoundTag profile, UUID uuid) {
CompoundTag properties = owner.get("Properties"); ListTag properties = profile.get("properties");
if (properties == null) { if (properties == null) {
if (uuid != null && uuid.version() == 4) { if (uuid != null && uuid.version() == 4) {
String uuidString = uuid.toString().replace("-", ""); String uuidString = uuid.toString().replace("-", "");
return SkinProvider.requestTexturesFromUUID(uuidString); return SkinProvider.requestTexturesFromUUID(uuidString);
} else if (owner.get("Name") instanceof StringTag nameTag) { } else if (profile.get("name") instanceof StringTag nameTag) {
// Fall back to username if UUID was missing or was an offline mode UUID // Fall back to username if UUID was missing or was an offline mode UUID
return SkinProvider.requestTexturesFromUsername(nameTag.getValue()); return SkinProvider.requestTexturesFromUsername(nameTag.getValue());
} }
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
ListTag textures = properties.get("textures"); LinkedHashMap<?,?> tag1 = (LinkedHashMap<?,?>) properties.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()); return CompletableFuture.completedFuture(texture.getValue());
} }
public static @Nullable BlockDefinition translateSkull(GeyserSession session, CompoundTag tag, Vector3i blockPosition, int blockState) { public static @Nullable BlockDefinition translateSkull(GeyserSession session, CompoundTag tag, Vector3i blockPosition, int blockState) {
// TODO: The tag layout follows new format (profille, etc...) CompoundTag profile = tag.get("profile");
CompoundTag owner = tag.get("SkullOwner"); if (profile == null) {
if (owner == null) {
session.getSkullCache().removeSkull(blockPosition); session.getSkullCache().removeSkull(blockPosition);
return null; return null;
} }
UUID uuid = getUUID(owner); UUID uuid = getUUID(profile);
CompletableFuture<String> texturesFuture = getTextures(owner, uuid); CompletableFuture<String> texturesFuture = getTextures(profile, uuid);
if (texturesFuture.isDone()) { if (texturesFuture.isDone()) {
try { try {
String texture = texturesFuture.get(); String texture = texturesFuture.get();
if (texture == null) { if (texture == null) {
session.getGeyser().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag); session.getGeyser().getLogger().debug("Custom skull with invalid profile tag: " + blockPosition + " " + tag);
return null; return null;
} }
SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texture, blockState); SkullCache.Skull skull = session.getSkullCache().putSkull(blockPosition, uuid, texture, blockState);
@ -128,10 +126,10 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
return null; return null;
} }
// SkullOwner contained a username, so we have to wait for it to be retrieved // profile contained a username, so we have to wait for it to be retrieved
texturesFuture.whenComplete((texturesProperty, throwable) -> { texturesFuture.whenComplete((texturesProperty, throwable) -> {
if (texturesProperty == null) { if (texturesProperty == null) {
session.getGeyser().getLogger().debug("Custom skull with invalid SkullOwner tag: " + blockPosition + " " + tag); session.getGeyser().getLogger().debug("Custom skull with invalid profile tag: " + blockPosition + " " + tag);
return; return;
} }
if (session.getEventLoop().inEventLoop()) { if (session.getEventLoop().inEventLoop()) {

View file

@ -71,7 +71,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
packet.getNbt(), blockState), packet.getPosition()); packet.getNbt(), blockState), packet.getPosition());
// Check for custom skulls. // Check for custom skulls.
boolean hasCustomHeadBlock = false; boolean hasCustomHeadBlock = false;
if (session.getPreferencesCache().showCustomSkulls() && packet.getNbt() != null && packet.getNbt().contains("SkullOwner")) { if (session.getPreferencesCache().showCustomSkulls() && packet.getNbt() != null && packet.getNbt().contains("profile")) {
BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, packet.getNbt(), position, blockState); BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, packet.getNbt(), position, blockState);
if (blockDefinition != null) { if (blockDefinition != null) {
hasCustomHeadBlock = true; hasCustomHeadBlock = true;

View file

@ -422,8 +422,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
} }
// Check for custom skulls // Check for custom skulls
// TODO: The tag layout follows new format (profille, etc...) if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.contains("profile")) {
if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.contains("SkullOwner")) {
BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, tag, Vector3i.from(x + chunkBlockX, y, z + chunkBlockZ), blockState); BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, tag, Vector3i.from(x + chunkBlockX, y, z + chunkBlockZ), blockState);
if (blockDefinition != null) { if (blockDefinition != null) {
int bedrockSectionY = (y >> 4) - (bedrockDimension.minY() >> 4); int bedrockSectionY = (y >> 4) - (bedrockDimension.minY() >> 4);