Add random skin to nicked players

This commit is contained in:
Electroid 2017-07-25 09:49:07 -07:00
parent 64b19191db
commit 1d0adf7283
3 changed files with 62 additions and 10 deletions

View File

@ -1,6 +1,7 @@
package tc.oc.commons.bukkit.chat;
import java.util.Set;
import java.util.stream.Stream;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -29,7 +30,15 @@ public class FlairRenderer implements PartialNameRenderer {
@Override
public String getLegacyName(Identity identity, NameType type) {
if(!(type.style.contains(NameFlag.FLAIR) && type.reveal)) return "";
return getFlairs(identity).reduce("", String::concat);
}
@Override
public BaseComponent getComponentName(Identity identity, NameType type) {
return Components.fromLegacyText(getLegacyName(identity, type));
}
public Stream<String> getFlairs(Identity identity) {
final UserDoc.Identity user;
if(identity.getPlayerId() instanceof UserDoc.Identity) {
// Flair may already be stashed inside the Identity
@ -37,19 +46,18 @@ public class FlairRenderer implements PartialNameRenderer {
} else {
user = userStore.tryUser(identity.getPlayerId());
}
if(user == null) return "";
if(user == null) return Stream.empty();
final Set<String> realms = ImmutableSet.copyOf(minecraftService.getLocalServer().realms());
return user.minecraft_flair()
.stream()
.filter(flair -> realms.contains(flair.realm))
.map(flair -> flair.text)
.reduce("", String::concat);
.stream()
.filter(flair -> realms.contains(flair.realm))
.map(flair -> flair.text);
}
@Override
public BaseComponent getComponentName(Identity identity, NameType type) {
return Components.fromLegacyText(getLegacyName(identity, type));
public int getNumberOfFlairs(Identity identity) {
return (int) getFlairs(identity).count();
}
}

View File

@ -4,6 +4,8 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import org.bukkit.Skin;
import org.bukkit.entity.Player;
import org.bukkit.scoreboard.Scoreboard;
@ -14,6 +16,10 @@ import tc.oc.commons.bukkit.chat.NameStyle;
import tc.oc.commons.bukkit.chat.NameType;
import tc.oc.commons.core.scheduler.Scheduler;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* Manages the Bukkit aspects of a player's name and appearance
*/
@ -29,6 +35,8 @@ public class PlayerAppearanceChanger {
private final FullNameRenderer nameRenderer;
private final UsernameRenderer usernameRenderer;
private final FlairRenderer flairRenderer;
private final Map<String, Skin> skinAssigned;
private final Cache<Skin, Integer> skinPool;
@Inject
PlayerAppearanceChanger(IdentityProvider identityProvider, NicknameConfiguration config, Scheduler scheduler, FullNameRenderer nameRenderer, UsernameRenderer usernameRenderer, FlairRenderer flairRenderer) {
@ -38,6 +46,11 @@ public class PlayerAppearanceChanger {
this.nameRenderer = nameRenderer;
this.usernameRenderer = usernameRenderer;
this.flairRenderer = flairRenderer;
this.skinAssigned = new HashMap<>();
this.skinPool = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS)
.maximumSize(30)
.build();
}
/**
@ -83,6 +96,7 @@ public class PlayerAppearanceChanger {
* Release any resources being used to maintain the given player's appearance
*/
public void cleanupAfterPlayer(Player player) {
skinPool.put(player.getRealSkin(), flairRenderer.getNumberOfFlairs(identityProvider.createIdentity(player)));
if(config.overheadFlair()) {
// Remove players from their "overhead flair team" on quit
final Team team = player.getServer().getScoreboardManager().getMainScoreboard().getPlayerTeam(player);
@ -100,7 +114,7 @@ public class PlayerAppearanceChanger {
player.setFakeNameAndSkin(viewer, null, null);
player.setFakeDisplayName(viewer, null);
} else {
player.setFakeNameAndSkin(viewer, identity.getNickname(), Skin.EMPTY);
player.setFakeNameAndSkin(viewer, identity.getNickname(), getRandomSkin(fakeDisplayName));
player.setFakeDisplayName(viewer, fakeDisplayName);
}
}
@ -125,4 +139,34 @@ public class PlayerAppearanceChanger {
private @Nullable String renderLegacyNickname(Identity identity) {
return identity.getNickname() == null ? null : nameRenderer.getLegacyName(identity, NICKNAME_TYPE);
}
/**
* Get a random skin from users that have recently disconnected.
* Prioritize skins that come from players with fewer flairs.
*/
private Skin getRandomSkin(@Nullable String nickname) {
Skin skin;
if(skinAssigned.containsKey(nickname)) {
skin = skinAssigned.get(nickname);
} else {
skin = skinPool.asMap()
.entrySet()
.stream()
.sorted(Map.Entry.<Skin, Integer>comparingByValue()
.reversed()
.thenComparing(entry -> entry.getKey().hashCode()))
.map(Map.Entry::getKey)
.findAny()
.orElse(null);
if(skin != null) {
skinPool.invalidate(skin);
} else {
skin = Skin.EMPTY;
}
if(nickname != null) {
skinAssigned.put(nickname, skin);
}
}
return skin;
}
}

View File

@ -76,7 +76,7 @@ public class PlayerTabEntry extends DynamicTabEntry {
@Override
public @Nullable Skin getSkin(TabView view) {
final Identity identity = identityProvider.currentIdentity(player);
return identity.isDisguised(view.getViewer()) ? null : player.getSkin();
return identity.isDisguised(view.getViewer()) ? player.getFakeSkin(view.getViewer()) : player.getSkin();
}
// Dispatched by TabManager