diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/SkinCommand.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/SkinCommand.java index c0c4455..6fbe14d 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/SkinCommand.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/command/impl/SkinCommand.java @@ -53,7 +53,7 @@ public class SkinCommand extends AbstractCommand { } try { - this.manager.useSkinAsync(fake, player) + this.manager.useOnlineSkinAsync(fake, player) .thenAcceptAsync(success -> { manager.rememberSkin(sender, fake, player); Bukkit.getScheduler().runTask(Main.getInstance(), () -> { diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/config/FakeplayerConfig.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/config/FakeplayerConfig.java index 75f8128..4d0f772 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/config/FakeplayerConfig.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/config/FakeplayerConfig.java @@ -1,6 +1,7 @@ package io.github.hello09x.fakeplayer.core.config; +import com.google.common.annotations.Beta; import com.google.inject.Inject; import com.google.inject.Singleton; import io.github.hello09x.devtools.core.config.PluginConfig; @@ -138,6 +139,12 @@ public class FakeplayerConfig extends PluginConfig { */ private PreventKicking preventKicking; + /** + * 真实皮肤 + */ + @Beta + private boolean defaultOnlineSkin; + @Inject public FakeplayerConfig() { super(Main.getInstance()); @@ -161,8 +168,6 @@ public class FakeplayerConfig extends PluginConfig { this.afterSpawnCommands = file.getStringList("after-spawn-commands"); this.postQuitCommands = file.getStringList("post-quit-commands"); this.afterQuitCommands = file.getStringList("after-quit-commands"); -// this.preparingCommands = file.getStringList("preparing-commands"); -// this.destroyCommands = file.getStringList("destroy-commands"); this.nameTemplate = file.getString("name-template", ""); this.dropInventoryOnQuiting = file.getBoolean("drop-inventory-on-quiting", true); this.persistData = file.getBoolean("persist-data", true); @@ -177,6 +182,8 @@ public class FakeplayerConfig extends PluginConfig { .map(c -> c.startsWith("/") ? c.substring(1) : c) .filter(c -> !c.isBlank()) .collect(Collectors.toSet()); + + this.defaultOnlineSkin = file.getBoolean("default-online-skin", false); this.debug = file.getBoolean("debug", false); if (this.isFileConfigurationOutOfDate()) { diff --git a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/FakeplayerSkinManager.java b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/FakeplayerSkinManager.java index a5b2f7e..07f982c 100644 --- a/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/FakeplayerSkinManager.java +++ b/fakeplayer-core/src/main/java/io/github/hello09x/fakeplayer/core/manager/FakeplayerSkinManager.java @@ -1,6 +1,7 @@ package io.github.hello09x.fakeplayer.core.manager; import com.destroystokyo.paper.profile.PlayerProfile; +import com.google.common.base.Throwables; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.errorprone.annotations.CanIgnoreReturnValue; @@ -8,6 +9,7 @@ import com.google.inject.Inject; import com.google.inject.Singleton; import io.github.hello09x.devtools.core.utils.SchedulerUtils; import io.github.hello09x.fakeplayer.core.Main; +import io.github.hello09x.fakeplayer.core.config.FakeplayerConfig; import io.github.hello09x.fakeplayer.core.repository.FakePlayerSkinRepository; import io.github.hello09x.fakeplayer.core.repository.model.FakePlayerSkin; import org.bukkit.Bukkit; @@ -17,8 +19,10 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import java.time.Duration; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; +import java.util.logging.Logger; /** * @author tanyaofei @@ -27,15 +31,18 @@ import java.util.concurrent.CompletableFuture; @Singleton public class FakeplayerSkinManager { + private final static Logger log = Main.getInstance().getLogger(); private final FakePlayerSkinRepository repository; + private final FakeplayerConfig config; private final Cache profileCache = CacheBuilder .newBuilder() .expireAfterWrite(Duration.ofHours(1)) .build(); @Inject - public FakeplayerSkinManager(FakePlayerSkinRepository repository) { + public FakeplayerSkinManager(FakePlayerSkinRepository repository, FakeplayerConfig config) { this.repository = repository; + this.config = config; } @CanIgnoreReturnValue @@ -54,18 +61,28 @@ public class FakeplayerSkinManager { public void useDefaultSkin(@NotNull CommandSender creator, @NotNull Player to) { if (!(creator instanceof Player p)) { + // 非玩家创建的假人只能采用在线皮肤 + if (config.isDefaultOnlineSkin()) { + this.useOnlineSkinAsync(to, Bukkit.getOfflinePlayer(to.getName())); + return; + } return; } // 使用以前配置过的 var skin = repository.selectByCreatorIdAndPlayerId(p.getUniqueId(), to.getUniqueId()); if (skin != null) { - this.useSkinAsync(to, Bukkit.getOfflinePlayer(skin.targetId())); + this.useOnlineSkinAsync(to, Bukkit.getOfflinePlayer(skin.targetId())); return; } - // 使用召唤者皮肤 - this.useSkin(to, p); + if (config.isDefaultOnlineSkin()) { + // 使用真实皮肤 + this.useOnlineSkinAsync(to, Bukkit.getOfflinePlayer(to.getName())); + } else { + // 使用召唤者皮肤 + this.useSkin(to, p); + } } @CanIgnoreReturnValue @@ -83,28 +100,48 @@ public class FakeplayerSkinManager { } @CanIgnoreReturnValue - public @NotNull CompletableFuture useSkinAsync(@NotNull Player to, @NotNull OfflinePlayer from) { + public @NotNull CompletableFuture useOnlineSkinAsync(@NotNull Player to, @NotNull OfflinePlayer from) { if (this.useSkin(to, from)) { return CompletableFuture.completedFuture(true); } var profile = from.getPlayerProfile(); return CompletableFuture - .supplyAsync(profile::complete) - .thenComposeAsync(success -> { - if (success && profile.hasTextures()) { + .supplyAsync(() -> { + try { + return profile.complete() ? ProfileCompleteResult.SUCCESS : ProfileCompleteResult.FAILED; + } catch (Exception e) { + log.warning("Failed to update skin of fake player %s since could not fetch online profile from mojang\n%s".formatted( + Optional.ofNullable(from.getName()) + .orElse(from.getUniqueId().toString()), + Throwables.getStackTraceAsString(e) + )); + return ProfileCompleteResult.ERROR; + } + }) + .thenComposeAsync(result -> { + if (result == ProfileCompleteResult.SUCCESS && profile.hasTextures()) { profileCache.put(from.getUniqueId(), profile); } - return SchedulerUtils.runTask(Main.getInstance(), () -> { - if (!success) { - return false; + + return SchedulerUtils.runTask(Main.getInstance(), () -> switch (result) { + case SUCCESS -> { + try { + this.setTexture(to, profile); + yield true; + } catch (Exception e) { + yield false; + } } - try { - this.setTexture(to, profile); - return true; - } catch (Exception e) { - return false; + case FAILED -> { + log.warning("Failed to update online skin of fakeplayer %s, maybe not a real player".formatted( + Optional.ofNullable(from.getName()) + .orElse(from.getUniqueId().toString())) + ); + yield false; } + case ERROR -> false; + }); }); } @@ -116,5 +153,11 @@ public class FakeplayerSkinManager { to.setPlayerProfile(toProfile); } + private enum ProfileCompleteResult { + SUCCESS, + FAILED, + ERROR + } + }