Citizens2/main/src/main/java/net/citizensnpcs/trait/SkinTrait.java

187 lines
5.1 KiB
Java

package net.citizensnpcs.trait;
import com.google.common.base.Charsets;
import com.google.common.base.Preconditions;
import com.google.common.io.BaseEncoding;
import net.citizensnpcs.Settings.Setting;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitName;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.Placeholders;
import net.citizensnpcs.npc.skin.SkinnableEntity;
import net.md_5.bungee.api.ChatColor;
@TraitName("skintrait")
public class SkinTrait extends Trait {
@Persist
private boolean fetchDefaultSkin = true;
private String filledPlaceholder;
@Persist
private String signature;
@Persist
private String skinName;
@Persist
private String textureRaw;
private int timer;
@Persist
private boolean updateSkins = Setting.NPC_SKIN_USE_LATEST.asBoolean();
public SkinTrait() {
super("skintrait");
}
private void checkPlaceholder(boolean update) {
if (skinName == null)
return;
String filled = ChatColor.stripColor(Placeholders.replace(skinName, null, npc).toLowerCase());
if (!filled.equalsIgnoreCase(skinName) && !filled.equalsIgnoreCase(filledPlaceholder)) {
filledPlaceholder = filled;
if (update) {
onSkinChange(true);
}
}
}
/**
* Clears skin texture and name.
*/
public void clearTexture() {
textureRaw = null;
signature = null;
skinName = null;
}
/**
* Whether to fetch the Mojang skin using the NPC's name on spawn.
*/
public boolean fetchDefaultSkin() {
return fetchDefaultSkin;
}
/**
* @return The texture signature, or null
*/
public String getSignature() {
return signature;
}
/**
* @return The skin name if set, or null (i.e. using the NPC's name)
*/
public String getSkinName() {
return filledPlaceholder != null && skinName != null ? filledPlaceholder
: skinName == null ? skinName : skinName.toLowerCase();
}
/**
* @return The encoded texture data, or null
*/
public String getTexture() {
return textureRaw;
}
@Override
public void load(DataKey key) {
checkPlaceholder(false);
}
private void onSkinChange(boolean forceUpdate) {
if (npc.isSpawned() && npc.getEntity() instanceof SkinnableEntity) {
((SkinnableEntity) npc.getEntity()).getSkinTracker().notifySkinChange(forceUpdate);
}
}
@Override
public void run() {
if (timer-- > 0)
return;
timer = Setting.PLACEHOLDER_SKIN_UPDATE_FREQUENCY.asTicks();
checkPlaceholder(true);
}
/**
* @see #fetchDefaultSkin
*/
public void setFetchDefaultSkin(boolean fetch) {
this.fetchDefaultSkin = fetch;
}
/**
* @see #shouldUpdateSkins()
*/
public void setShouldUpdateSkins(boolean update) {
this.updateSkins = update;
}
/**
* Sets the skin name - will respawn NPC if spawned.
*
* @param name
* The skin name
*/
public void setSkinName(String name) {
setSkinName(name, false);
}
/**
* Sets the skin name - will respawn NPC if spawned.
*
* @param name
* The skin name
* @param forceUpdate
* Whether to force update if no data has been fetched yet
* @see net.citizensnpcs.npc.skin.Skin#get(SkinnableEntity, boolean)
*/
public void setSkinName(String name, boolean forceUpdate) {
Preconditions.checkNotNull(name);
setSkinNameInternal(name);
onSkinChange(forceUpdate);
}
private void setSkinNameInternal(String name) {
skinName = ChatColor.stripColor(name);
checkPlaceholder(false);
}
/**
* Sets the skin data directly, respawning the NPC if spawned
*
* @param skinName
* Skin name, for caching purposes
* @param signature
* {@link #getSignature()}
* @param data
* {@link #getTexture()}
*/
public void setSkinPersistent(String skinName, String signature, String data) {
Preconditions.checkNotNull(skinName);
Preconditions.checkNotNull(signature);
Preconditions.checkNotNull(data);
setSkinNameInternal(skinName);
String json = new String(BaseEncoding.base64().decode(data), Charsets.UTF_8);
if (!json.contains("textures")) {
throw new IllegalArgumentException("Invalid texture data");
}
this.signature = signature;
this.textureRaw = data;
this.updateSkins = false;
npc.data().setPersistent("cached-skin-uuid-name", skinName.toLowerCase());
onSkinChange(false);
}
public void setTexture(String value, String signature) {
this.textureRaw = value;
this.signature = signature;
}
/**
* @return Whether the skin should be updated from Mojang periodically
*/
public boolean shouldUpdateSkins() {
return updateSkins;
}
}