Force skin updates on /npc skin -p

This commit is contained in:
fullwall 2016-05-20 16:41:02 +08:00
parent 5a066d27b5
commit 01ed1dd0d4
6 changed files with 79 additions and 48 deletions

View File

@ -1481,7 +1481,7 @@ public class NPCCommands {
SkinnableEntity skinnable = NMS.getSkinnable(npc.getEntity());
if (skinnable != null) {
skinnable.setSkinName(skinName);
skinnable.setSkinName(skinName, args.hasFlag('p'));
}
}
}

View File

@ -348,10 +348,15 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable
@Override
public void setSkinName(String name) {
setSkinName(name, false);
}
@Override
public void setSkinName(String name, boolean forceUpdate) {
Preconditions.checkNotNull(name);
npc.data().setPersistent(NPC.PLAYER_SKIN_UUID_METADATA, name.toLowerCase());
skinTracker.notifySkinChange();
skinTracker.notifySkinChange(forceUpdate);
}
public void setTargetLook(Entity target, float yawOffset, float renderOffset) {
@ -455,8 +460,14 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable
public void setSkinName(String name) {
((SkinnableEntity) this.entity).setSkinName(name);
}
@Override
public void setSkinName(String skinName, boolean forceUpdate) {
((SkinnableEntity) this.entity).setSkinName(skinName, forceUpdate);
}
}
private static final float EPSILON = 0.005F;
private static final Location LOADED_LOCATION = new Location(null, 0, 0, 0);
}

View File

@ -1,6 +1,7 @@
package net.citizensnpcs.npc.profile;
import java.util.Collection;
import javax.annotation.Nullable;
import org.bukkit.Bukkit;
@ -45,10 +46,8 @@ public class ProfileFetcher {
}
repo.findProfilesByNames(playerNames, Agent.MINECRAFT, new ProfileLookupCallback() {
@Override
public void onProfileLookupFailed(GameProfile profile, Exception e) {
if (Messaging.isDebugging()) {
Messaging.debug(
"Profile lookup for player '" + profile.getName() + "' failed: " + getExceptionMsg(e));
@ -69,7 +68,6 @@ public class ProfileFetcher {
@Override
public void onProfileLookupSucceeded(final GameProfile profile) {
if (Messaging.isDebugging()) {
Messaging.debug("Fetched profile " + profile.getId() + " for player " + profile.getName());
}
@ -81,7 +79,6 @@ public class ProfileFetcher {
try {
request.setResult(NMS.fillProfileProperties(profile, true), ProfileFetchResult.SUCCESS);
} catch (Exception e) {
if (Messaging.isDebugging()) {
Messaging.debug(
"Profile lookup for player '" + profile.getName() + "' failed: " + getExceptionMsg(e));
@ -114,20 +111,14 @@ public class ProfileFetcher {
PROFILE_THREAD.fetch(name, handler);
}
/**
* Clear all queued and cached requests.
*/
public static void reset() {
initThread();
}
@Nullable
private static ProfileRequest findRequest(String name, Collection<ProfileRequest> requests) {
name = name.toLowerCase();
for (ProfileRequest request : requests) {
if (request.getPlayerName().equals(name))
if (request.getPlayerName().equals(name)) {
return request;
}
}
return null;
}
@ -138,6 +129,15 @@ public class ProfileFetcher {
return cause != null ? cause : message;
}
private static void initThread() {
if (THREAD_TASK != null) {
THREAD_TASK.cancel();
}
PROFILE_THREAD = new ProfileFetchThread();
THREAD_TASK = Bukkit.getScheduler().runTaskTimerAsynchronously(CitizensAPI.getPlugin(), PROFILE_THREAD, 21, 20);
}
private static boolean isProfileNotFound(Exception e) {
String message = e.getMessage();
String cause = e.getCause() != null ? e.getCause().getMessage() : null;
@ -155,13 +155,11 @@ public class ProfileFetcher {
|| (cause != null && cause.contains("too many requests"));
}
private static void initThread() {
if (THREAD_TASK != null)
THREAD_TASK.cancel();
PROFILE_THREAD = new ProfileFetchThread();
THREAD_TASK = Bukkit.getScheduler().runTaskTimerAsynchronously(
CitizensAPI.getPlugin(), PROFILE_THREAD, 21, 20);
/**
* Clear all queued and cached requests.
*/
public static void reset() {
initThread();
}
private static ProfileFetchThread PROFILE_THREAD;

View File

@ -44,6 +44,7 @@ public class Skin {
*
* @param skinName
* The name of the player the skin belongs to.
* @param forceUpdate
*/
Skin(String skinName) {
this.skinName = skinName.toLowerCase();
@ -205,6 +206,7 @@ public class Skin {
}
private void setData(@Nullable GameProfile profile) {
System.out.println("SET DATA");
if (profile == null) {
isValid = false;
return;
@ -251,10 +253,26 @@ public class Skin {
* The skinnable entity.
*/
public static Skin get(SkinnableEntity entity) {
return get(entity, false);
}
/**
* Get a skin for a skinnable entity.
*
* <p>
* If a Skin instance does not exist, a new one is created and the skin data is automatically fetched.
* </p>
*
* @param entity
* The skinnable entity.
* @param forceUpdate
* if the skin should be checked via the cache
*/
public static Skin get(SkinnableEntity entity, boolean forceUpdate) {
Preconditions.checkNotNull(entity);
String skinName = entity.getSkinName().toLowerCase();
return get(skinName);
return get(skinName, forceUpdate);
}
/**
@ -267,7 +285,7 @@ public class Skin {
* @param skinName
* The name of the skin.
*/
public static Skin get(String skinName) {
public static Skin get(String skinName, boolean forceUpdate) {
Preconditions.checkNotNull(skinName);
skinName = skinName.toLowerCase();
@ -279,6 +297,8 @@ public class Skin {
if (skin == null) {
skin = new Skin(skinName);
} else if (forceUpdate) {
skin.fetch();
}
return skin;

View File

@ -94,28 +94,11 @@ public class SkinPacketTracker {
/**
* Notify that the NPC skin has been changed.
*/
public void notifySkinChange() {
this.skin = Skin.get(entity);
public void notifySkinChange(boolean forceUpdate) {
this.skin = Skin.get(entity, forceUpdate);
skin.applyAndRespawn(entity);
}
/**
* Invoke when the NPC entity is spawned.
*/
public void onSpawnNPC() {
isRemoved = false;
new BukkitRunnable() {
@Override
public void run() {
if (!entity.getNPC().isSpawned())
return;
double viewDistance = Settings.Setting.NPC_SKIN_VIEW_DISTANCE.asDouble();
updateNearbyViewers(viewDistance);
}
}.runTaskLater(CitizensAPI.getPlugin(), 20);
}
/**
* Invoke when the NPC entity is removed.
*
@ -139,6 +122,23 @@ public class SkinPacketTracker {
}
}
/**
* Invoke when the NPC entity is spawned.
*/
public void onSpawnNPC() {
isRemoved = false;
new BukkitRunnable() {
@Override
public void run() {
if (!entity.getNPC().isSpawned())
return;
double viewDistance = Settings.Setting.NPC_SKIN_VIEW_DISTANCE.asDouble();
updateNearbyViewers(viewDistance);
}
}.runTaskLater(CitizensAPI.getPlugin(), 20);
}
private void scheduleRemovePacket(final PlayerEntry entry) {
if (isRemoved)
return;
@ -162,8 +162,7 @@ public class SkinPacketTracker {
}
private boolean shouldRemoveFromTabList() {
return entity.getNPC().data().get("removefromtablist",
Settings.Setting.DISABLE_TABLIST.asBoolean());
return entity.getNPC().data().get("removefromtablist", Settings.Setting.DISABLE_TABLIST.asBoolean());
}
/**

View File

@ -1,9 +1,11 @@
package net.citizensnpcs.npc.skin;
import com.mojang.authlib.GameProfile;
import net.citizensnpcs.npc.ai.NPCHolder;
import org.bukkit.entity.Player;
import com.mojang.authlib.GameProfile;
import net.citizensnpcs.npc.ai.NPCHolder;
/**
* Interface for player entities that are skinnable.
*/
@ -42,8 +44,7 @@ public interface SkinnableEntity extends NPCHolder {
void setSkinFlags(byte flags);
/**
* Set the name of the player whose skin the NPC
* uses.
* Set the name of the player whose skin the NPC uses.
*
* <p>
* Setting the skin name automatically updates and respawn the NPC.
@ -53,4 +54,6 @@ public interface SkinnableEntity extends NPCHolder {
* The skin name.
*/
void setSkinName(String name);
void setSkinName(String skinName, boolean forceUpdate);
}