Skip to content

Commit

Permalink
fix(heads): Properly define custom textured heads
Browse files Browse the repository at this point in the history
  • Loading branch information
Machine-Maker committed Nov 25, 2023
1 parent 8d41d84 commit 2a2bda6
Show file tree
Hide file tree
Showing 4 changed files with 13 additions and 42 deletions.
1 change: 0 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ dependencies {
implementation(libs.commons.bean)

// Native to minecraft
compileOnly(libs.authlib)
compileOnly(libs.slf4j)

// soft dependencies
Expand Down
2 changes: 0 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ commons-config = "2.8.0"
commons-beans = "1.9.4"

# compile only
authlib = "5.0.47"
slf4j-api = "2.0.7" # only until paper bumps api version
brigadier = "1.1.8"

Expand Down Expand Up @@ -52,7 +51,6 @@ commons-config = { module = "org.apache.commons:commons-configuration2", version
commons-bean = { module = "commons-beanutils:commons-beanutils", version.ref = "commons-beans" }

# compile only
authlib = { module = "com.mojang:authlib", version.ref = "authlib" }
slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j-api" }
brigadier = {module = "com.mojang:brigadier", version.ref = "brigadier" }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
*/
package me.machinemaker.papertweaks.modules.items.playerheaddrops;

import com.destroystokyo.paper.profile.PlayerProfile;
import com.google.inject.Inject;
import com.mojang.authlib.GameProfile;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import me.machinemaker.papertweaks.modules.ModuleListener;
Expand Down Expand Up @@ -59,9 +59,9 @@ public void onPlayerKilledByPlayer(final PlayerDeathEvent event) {
final @Nullable SkullMeta meta = (SkullMeta) skull.getItemMeta();
if (meta == null) return; // shouldn't be possible

final GameProfile profile = PTUtils.getGameProfile(event.getEntity());
final PlayerProfile profile = event.getEntity().getPlayerProfile();
PTUtils.sanitizeTextures(profile);
PTUtils.loadMeta(meta, profile);
meta.setPlayerProfile(profile);
if (killer != null) {
meta.lore(List.of(text("Killed by " + killer.getName())));
}
Expand Down
46 changes: 10 additions & 36 deletions src/main/java/me/machinemaker/papertweaks/utils/PTUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,11 @@
*/
package me.machinemaker.papertweaks.utils;

import com.google.common.collect.Iterables;
import com.destroystokyo.paper.profile.PlayerProfile;
import com.destroystokyo.paper.profile.ProfileProperty;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
Expand All @@ -35,9 +34,6 @@
import java.util.Objects;
import java.util.UUID;
import java.util.function.Consumer;
import me.machinemaker.mirror.FieldAccessor;
import me.machinemaker.mirror.MethodInvoker;
import me.machinemaker.mirror.Mirror;
import me.machinemaker.mirror.paper.PaperMirror;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
Expand All @@ -64,10 +60,6 @@ public final class PTUtils {

private static final Class<?> CRAFT_PLAYER_CLASS = PaperMirror.getCraftBukkitClass("entity.CraftPlayer");
private static final Class<?> NMS_PLAYER_CLASS = PaperMirror.findMinecraftClass("world.entity.player.EntityHuman", "world.entity.player.Player");
private static final Class<?> CRAFT_META_SKULL_CLASS = PaperMirror.getCraftBukkitClass("inventory.CraftMetaSkull");
private static final FieldAccessor.Typed<GameProfile> CRAFT_META_ITEM_GAME_PROFILE = Mirror.typedFuzzyField(CRAFT_META_SKULL_CLASS, GameProfile.class).names("profile").find();
private static final MethodInvoker CRAFT_PLAYER_GET_HANDLE = Mirror.fuzzyMethod(CRAFT_PLAYER_CLASS, NMS_PLAYER_CLASS).names("getHandle").find();
private static final MethodInvoker.Typed<GameProfile> NMS_PLAYER_GET_PLAYER_PROFILE = Mirror.typedFuzzyMethod(NMS_PLAYER_CLASS, GameProfile.class).find();

private static final Gson GSON = new Gson();

Expand All @@ -93,13 +85,6 @@ public static Component sanitizeName(final String name) {
return GsonComponentSerializer.gson().deserializeFromTree(tree);
}

public static GameProfile getGameProfile(final Player player) {
final GameProfile live = Objects.requireNonNull(NMS_PLAYER_GET_PLAYER_PROFILE.invoke(CRAFT_PLAYER_GET_HANDLE.invoke(player)), () -> "unexpected null GameProfile from " + player);
final GameProfile copy = new GameProfile(live.getId(), live.getName());
copy.getProperties().putAll(live.getProperties());
return copy;
}

public static ItemStack getSkull(final Component name, final String texture) {
return getSkull(name, null, texture, 1);
}
Expand All @@ -118,31 +103,20 @@ public static ItemStack getSkull(final @Nullable Component name, final String ga
return skull;
}
final @Nullable SkullMeta meta = (SkullMeta) Objects.requireNonNull(skull.getItemMeta());
final GameProfile profile = new GameProfile(uuid == null ? UUID.randomUUID() : uuid, gameProfileName);
profile.getProperties().put("textures", new Property("textures", texture));
loadMeta(meta, profile, name);
final PlayerProfile profile = Bukkit.createProfile(uuid == null ? UUID.randomUUID() : uuid, gameProfileName);
profile.setProperty(new ProfileProperty("textures", texture));
meta.setPlayerProfile(profile);
skull.setItemMeta(meta);
return skull;
}

public static void sanitizeTextures(final GameProfile profile) {
final Property textures = Iterables.getFirst(profile.getProperties().get("textures"), null);
profile.getProperties().removeAll("textures");
public static void sanitizeTextures(final PlayerProfile profile) {
final @Nullable ProfileProperty textures = profile.getProperties().stream().filter(property -> property.getName().equals("textures")).findFirst().orElse(null);
profile.removeProperty("textures");
if (textures != null) {
final JsonObject object = GSON.fromJson(new String(Base64.getDecoder().decode(textures.value()), StandardCharsets.UTF_8), JsonObject.class);
final JsonObject object = GSON.fromJson(new String(Base64.getDecoder().decode(textures.getValue()), StandardCharsets.UTF_8), JsonObject.class);
object.remove("timestamp");
profile.getProperties().put("textures", new Property("textures", Base64.getEncoder().encodeToString(GSON.toJson(object).getBytes(StandardCharsets.UTF_8))));
}
}

public static void loadMeta(final SkullMeta meta, final GameProfile profile) {
loadMeta(meta, profile, null);
}

public static void loadMeta(final SkullMeta meta, final GameProfile profile, final @Nullable Component name) {
CRAFT_META_ITEM_GAME_PROFILE.set(meta, profile);
if (name != null) {
loadMeta(meta, name);
profile.setProperty(new ProfileProperty("textures", Base64.getEncoder().encodeToString(GSON.toJson(object).getBytes(StandardCharsets.UTF_8))));
}
}

Expand Down

0 comments on commit 2a2bda6

Please sign in to comment.