Merge branch '0.3.9'

This commit is contained in:
tanyaofei 2024-08-11 21:32:03 +08:00
commit 31a3d4e598
3 changed files with 69 additions and 19 deletions

View File

@ -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(), () -> {

View File

@ -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()) {

View File

@ -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<UUID, PlayerProfile> 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<Boolean> useSkinAsync(@NotNull Player to, @NotNull OfflinePlayer from) {
public @NotNull CompletableFuture<Boolean> 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
}
}