Change NPC UUID version to 2 for Minecraft

This commit is contained in:
fullwall 2014-11-15 15:47:41 +08:00
parent 651fbac979
commit 7008ffd013
2 changed files with 224 additions and 224 deletions

View File

@ -23,238 +23,235 @@ import org.bukkit.craftbukkit.v1_7_R4.entity.CraftEntity;
import org.bukkit.entity.LivingEntity; import org.bukkit.entity.LivingEntity;
public class MCTargetStrategy implements PathStrategy, EntityTarget { public class MCTargetStrategy implements PathStrategy, EntityTarget {
private final boolean aggro; private final boolean aggro;
private int attackTicks; private int attackTicks;
private CancelReason cancelReason; private CancelReason cancelReason;
private final Entity handle; private final Entity handle;
private final NPC npc; private final NPC npc;
private final NavigatorParameters parameters; private final NavigatorParameters parameters;
private final Entity target; private final Entity target;
private final TargetNavigator targetNavigator; private final TargetNavigator targetNavigator;
public MCTargetStrategy(NPC npc, org.bukkit.entity.Entity target, boolean aggro, public MCTargetStrategy(NPC npc, org.bukkit.entity.Entity target, boolean aggro, NavigatorParameters params) {
NavigatorParameters params) { this.npc = npc;
this.npc = npc; this.parameters = params;
this.parameters = params; this.handle = ((CraftEntity) npc.getEntity()).getHandle();
this.handle = ((CraftEntity) npc.getEntity()).getHandle(); this.target = ((CraftEntity) target).getHandle();
this.target = ((CraftEntity) target).getHandle(); Navigation nav = NMS.getNavigation(this.handle);
Navigation nav = NMS.getNavigation(this.handle); this.targetNavigator = nav != null && !params.useNewPathfinder() ? new NavigationFieldWrapper(nav)
this.targetNavigator = nav != null && !params.useNewPathfinder() ? new NavigationFieldWrapper( : new AStarTargeter();
nav) : new AStarTargeter(); this.aggro = aggro;
this.aggro = aggro; }
}
private boolean canAttack() { private boolean canAttack() {
return attackTicks == 0 return attackTicks == 0
&& (handle.boundingBox.e > target.boundingBox.b && handle.boundingBox.b < target.boundingBox.e) && (handle.boundingBox.e > target.boundingBox.b && handle.boundingBox.b < target.boundingBox.e)
&& closeEnough(distanceSquared()) && hasLineOfSight(); && closeEnough(distanceSquared()) && hasLineOfSight();
} }
@Override @Override
public void clearCancelReason() { public void clearCancelReason() {
cancelReason = null; cancelReason = null;
} }
private boolean closeEnough(double distance) { private boolean closeEnough(double distance) {
return distance <= parameters.attackRange(); return distance <= parameters.attackRange();
} }
private double distanceSquared() { private double distanceSquared() {
return handle.getBukkitEntity().getLocation(HANDLE_LOCATION) return handle.getBukkitEntity().getLocation(HANDLE_LOCATION)
.distanceSquared(target.getBukkitEntity().getLocation(TARGET_LOCATION)); .distanceSquared(target.getBukkitEntity().getLocation(TARGET_LOCATION));
} }
@Override @Override
public CancelReason getCancelReason() { public CancelReason getCancelReason() {
return cancelReason; return cancelReason;
} }
@Override @Override
public LivingEntity getTarget() { public LivingEntity getTarget() {
return (LivingEntity) target.getBukkitEntity(); return (LivingEntity) target.getBukkitEntity();
} }
@Override @Override
public Location getTargetAsLocation() { public Location getTargetAsLocation() {
return getTarget().getLocation(); return getTarget().getLocation();
} }
@Override @Override
public TargetType getTargetType() { public TargetType getTargetType() {
return TargetType.ENTITY; return TargetType.ENTITY;
} }
private boolean hasLineOfSight() { private boolean hasLineOfSight() {
return ((LivingEntity) handle.getBukkitEntity()).hasLineOfSight(target.getBukkitEntity()); return ((LivingEntity) handle.getBukkitEntity()).hasLineOfSight(target.getBukkitEntity());
} }
@Override @Override
public boolean isAggressive() { public boolean isAggressive() {
return aggro; return aggro;
} }
private void setPath() { private void setPath() {
targetNavigator.setPath(); targetNavigator.setPath();
} }
@Override @Override
public void stop() { public void stop() {
targetNavigator.stop(); targetNavigator.stop();
} }
@Override @Override
public String toString() { public String toString() {
return "MCTargetStrategy [target=" + target + "]"; return "MCTargetStrategy [target=" + target + "]";
} }
@Override @Override
public boolean update() { public boolean update() {
if (target == null || !target.getBukkitEntity().isValid()) { if (target == null || !target.getBukkitEntity().isValid()) {
cancelReason = CancelReason.TARGET_DIED; cancelReason = CancelReason.TARGET_DIED;
return true; return true;
} }
if (target.world != handle.world) { if (target.world != handle.world) {
cancelReason = CancelReason.TARGET_MOVED_WORLD; cancelReason = CancelReason.TARGET_MOVED_WORLD;
return true; return true;
} }
if (cancelReason != null) { if (cancelReason != null) {
return true; return true;
} }
if (target.world.getWorld().getFullTime() % 10 == 0) { if (target.world.getWorld().getFullTime() % 10 == 0) {
setPath(); setPath();
} }
NMS.look(handle, target); NMS.look(handle, target);
if (aggro && canAttack()) { if (aggro && canAttack()) {
AttackStrategy strategy = parameters.attackStrategy(); AttackStrategy strategy = parameters.attackStrategy();
if (strategy != null && strategy.handle((LivingEntity) handle.getBukkitEntity(), getTarget())) { if (strategy != null && strategy.handle((LivingEntity) handle.getBukkitEntity(), getTarget())) {
} else } else if (strategy != parameters.defaultAttackStrategy()) {
if (strategy != parameters.defaultAttackStrategy()) { parameters.defaultAttackStrategy().handle((LivingEntity) handle.getBukkitEntity(), getTarget());
parameters.defaultAttackStrategy().handle((LivingEntity) handle.getBukkitEntity(), }
getTarget()); attackTicks = ATTACK_DELAY_TICKS;
} }
attackTicks = ATTACK_DELAY_TICKS; if (attackTicks > 0) {
} attackTicks--;
if (attackTicks > 0) { }
attackTicks--;
}
return false; return false;
} }
private class AStarTargeter implements TargetNavigator { private class AStarTargeter implements TargetNavigator {
private int failureTimes = 0; private int failureTimes = 0;
private PathStrategy strategy; private PathStrategy strategy;
public AStarTargeter() { public AStarTargeter() {
setStrategy(); setStrategy();
} }
@Override @Override
public void setPath() { public void setPath() {
setStrategy(); setStrategy();
strategy.update(); strategy.update();
CancelReason subReason = strategy.getCancelReason(); CancelReason subReason = strategy.getCancelReason();
if (subReason == CancelReason.STUCK) { if (subReason == CancelReason.STUCK) {
if (failureTimes++ > 10) { if (failureTimes++ > 10) {
cancelReason = strategy.getCancelReason(); cancelReason = strategy.getCancelReason();
} }
} else { } else {
failureTimes = 0; failureTimes = 0;
cancelReason = strategy.getCancelReason(); cancelReason = strategy.getCancelReason();
} }
} }
private void setStrategy() { private void setStrategy() {
Location location = target.getBukkitEntity().getLocation(TARGET_LOCATION); Location location = target.getBukkitEntity().getLocation(TARGET_LOCATION);
strategy = npc.isFlyable() ? new FlyingAStarNavigationStrategy(npc, location, parameters) strategy = npc.isFlyable() ? new FlyingAStarNavigationStrategy(npc, location, parameters)
: new AStarNavigationStrategy(npc, location, parameters); : new AStarNavigationStrategy(npc, location, parameters);
} }
@Override @Override
public void stop() { public void stop() {
strategy.stop(); strategy.stop();
} }
} }
private class NavigationFieldWrapper implements TargetNavigator { private class NavigationFieldWrapper implements TargetNavigator {
boolean j = true, k, l, m; boolean j = true, k, l, m;
private final Navigation navigation; private final Navigation navigation;
float range; float range;
private NavigationFieldWrapper(Navigation navigation) { private NavigationFieldWrapper(Navigation navigation) {
this.navigation = navigation; this.navigation = navigation;
this.k = navigation.c(); this.k = navigation.c();
this.l = navigation.a(); this.l = navigation.a();
try { try {
if (navigation instanceof PlayerNavigation) { if (navigation instanceof PlayerNavigation) {
if (P_NAV_E != null) if (P_NAV_E != null)
range = (float) ((AttributeInstance) P_NAV_E.get(navigation)).getValue(); range = (float) ((AttributeInstance) P_NAV_E.get(navigation)).getValue();
if (P_NAV_J != null) if (P_NAV_J != null)
j = P_NAV_J.getBoolean(navigation); j = P_NAV_J.getBoolean(navigation);
if (P_NAV_M != null) if (P_NAV_M != null)
m = P_NAV_M.getBoolean(navigation); m = P_NAV_M.getBoolean(navigation);
} else { } else {
if (E_NAV_E != null) if (E_NAV_E != null)
range = (float) ((AttributeInstance) E_NAV_E.get(navigation)).getValue(); range = (float) ((AttributeInstance) E_NAV_E.get(navigation)).getValue();
if (E_NAV_J != null) if (E_NAV_J != null)
j = E_NAV_J.getBoolean(navigation); j = E_NAV_J.getBoolean(navigation);
if (E_NAV_M != null) if (E_NAV_M != null)
m = E_NAV_M.getBoolean(navigation); m = E_NAV_M.getBoolean(navigation);
} }
} catch (Exception ex) { } catch (Exception ex) {
range = parameters.range(); range = parameters.range();
} }
} }
public PathEntity findPath(Entity from, Entity to) { public PathEntity findPath(Entity from, Entity to) {
return handle.world.findPath(from, to, range, j, k, l, m); return handle.world.findPath(from, to, range, j, k, l, m);
} }
@Override @Override
public void setPath() { public void setPath() {
navigation.a(parameters.avoidWater()); navigation.a(parameters.avoidWater());
navigation.a(findPath(handle, target), parameters.speed()); navigation.a(findPath(handle, target), parameters.speed());
} }
@Override @Override
public void stop() { public void stop() {
NMS.stopNavigation(navigation); NMS.stopNavigation(navigation);
} }
} }
private static interface TargetNavigator { private static interface TargetNavigator {
void setPath(); void setPath();
void stop(); void stop();
} }
private static final int ATTACK_DELAY_TICKS = 20; private static final int ATTACK_DELAY_TICKS = 20;
static final AttackStrategy DEFAULT_ATTACK_STRATEGY = new AttackStrategy() { static final AttackStrategy DEFAULT_ATTACK_STRATEGY = new AttackStrategy() {
@Override @Override
public boolean handle(LivingEntity attacker, LivingEntity bukkitTarget) { public boolean handle(LivingEntity attacker, LivingEntity bukkitTarget) {
EntityLiving handle = NMS.getHandle(attacker); EntityLiving handle = NMS.getHandle(attacker);
EntityLiving target = NMS.getHandle(bukkitTarget); EntityLiving target = NMS.getHandle(bukkitTarget);
if (handle instanceof EntityPlayer) { if (handle instanceof EntityPlayer) {
EntityPlayer humanHandle = (EntityPlayer) handle; EntityPlayer humanHandle = (EntityPlayer) handle;
humanHandle.attack(target); humanHandle.attack(target);
PlayerAnimation.ARM_SWING.play(humanHandle.getBukkitEntity()); PlayerAnimation.ARM_SWING.play(humanHandle.getBukkitEntity());
} else { } else {
NMS.attack(handle, target); NMS.attack(handle, target);
} }
return false; return false;
} }
}; };
private static Field E_NAV_E, E_NAV_J, E_NAV_M; private static Field E_NAV_E, E_NAV_J, E_NAV_M;
private static final Location HANDLE_LOCATION = new Location(null, 0, 0, 0); private static final Location HANDLE_LOCATION = new Location(null, 0, 0, 0);
private static Field P_NAV_E, P_NAV_J, P_NAV_M; private static Field P_NAV_E, P_NAV_J, P_NAV_M;
private static final Location TARGET_LOCATION = new Location(null, 0, 0, 0); private static final Location TARGET_LOCATION = new Location(null, 0, 0, 0);
static { static {
E_NAV_E = NMS.getField(Navigation.class, "e"); E_NAV_E = NMS.getField(Navigation.class, "e");
E_NAV_J = NMS.getField(Navigation.class, "j"); E_NAV_J = NMS.getField(Navigation.class, "j");
E_NAV_M = NMS.getField(Navigation.class, "m"); E_NAV_M = NMS.getField(Navigation.class, "m");
P_NAV_E = NMS.getField(PlayerNavigation.class, "e"); P_NAV_E = NMS.getField(PlayerNavigation.class, "e");
P_NAV_J = NMS.getField(PlayerNavigation.class, "j"); P_NAV_J = NMS.getField(PlayerNavigation.class, "j");
P_NAV_M = NMS.getField(PlayerNavigation.class, "m"); P_NAV_M = NMS.getField(PlayerNavigation.class, "m");
} }
} }

View File

@ -61,7 +61,10 @@ public class HumanController extends AbstractEntityController {
UUID uuid = npc.getUniqueId(); UUID uuid = npc.getUniqueId();
if (uuid.version() == 4) { // clear version if (uuid.version() == 4) { // clear version
uuid = new UUID(uuid.getMostSignificantBits() | 0x0000000000005000L, uuid.getLeastSignificantBits()); long msb = uuid.getMostSignificantBits();
msb &= ~0x0000000000004000L;
msb |= 0x0000000000002000L;
uuid = new UUID(msb, uuid.getLeastSignificantBits());
} }
GameProfile profile = new GameProfile(uuid, coloredName); GameProfile profile = new GameProfile(uuid, coloredName);
@ -124,8 +127,8 @@ public class HumanController extends AbstractEntityController {
private GameProfile fillProfileProperties(YggdrasilAuthenticationService auth, GameProfile profile, private GameProfile fillProfileProperties(YggdrasilAuthenticationService auth, GameProfile profile,
boolean requireSecure) throws Exception { boolean requireSecure) throws Exception {
URL url = HttpAuthenticationService.constantURL(new StringBuilder() URL url = HttpAuthenticationService.constantURL(new StringBuilder()
.append("https://sessionserver.mojang.com/session/minecraft/profile/") .append("https://sessionserver.mojang.com/session/minecraft/profile/")
.append(UUIDTypeAdapter.fromUUID(profile.getId())).toString()); .append(UUIDTypeAdapter.fromUUID(profile.getId())).toString());
url = HttpAuthenticationService.concatenateURL(url, url = HttpAuthenticationService.concatenateURL(url,
new StringBuilder().append("unsigned=").append(!requireSecure).toString()); new StringBuilder().append("unsigned=").append(!requireSecure).toString());
MinecraftProfilePropertiesResponse response = (MinecraftProfilePropertiesResponse) MAKE_REQUEST.invoke( MinecraftProfilePropertiesResponse response = (MinecraftProfilePropertiesResponse) MAKE_REQUEST.invoke(
@ -152,7 +155,7 @@ public class HumanController extends AbstractEntityController {
if (cached != null) { if (cached != null) {
if (Messaging.isDebugging()) { if (Messaging.isDebugging()) {
Messaging Messaging
.debug("Using cached skin texture for NPC " + npc.getName() + " UUID " + npc.getUniqueId()); .debug("Using cached skin texture for NPC " + npc.getName() + " UUID " + npc.getUniqueId());
} }
skinProfile = new GameProfile(UUID.fromString(realUUID), ""); skinProfile = new GameProfile(UUID.fromString(realUUID), "");
skinProfile.getProperties().put("textures", cached); skinProfile.getProperties().put("textures", cached);
@ -164,7 +167,7 @@ public class HumanController extends AbstractEntityController {
} catch (Exception e) { } catch (Exception e) {
if ((e.getMessage() != null && e.getMessage().contains("too many requests")) if ((e.getMessage() != null && e.getMessage().contains("too many requests"))
|| (e.getCause() != null && e.getCause().getMessage() != null && e.getCause().getMessage() || (e.getCause() != null && e.getCause().getMessage() != null && e.getCause().getMessage()
.contains("too many requests"))) { .contains("too many requests"))) {
SKIN_THREAD.delay(); SKIN_THREAD.delay();
SKIN_THREAD.addRunnable(this); SKIN_THREAD.addRunnable(this);
} }
@ -254,22 +257,22 @@ public class HumanController extends AbstractEntityController {
.getGameProfileRepository(); .getGameProfileRepository();
repo.findProfilesByNames(new String[] { ChatColor.stripColor(reportedUUID) }, Agent.MINECRAFT, repo.findProfilesByNames(new String[] { ChatColor.stripColor(reportedUUID) }, Agent.MINECRAFT,
new ProfileLookupCallback() { new ProfileLookupCallback() {
@Override @Override
public void onProfileLookupFailed(GameProfile arg0, Exception arg1) { public void onProfileLookupFailed(GameProfile arg0, Exception arg1) {
throw new RuntimeException(arg1); throw new RuntimeException(arg1);
} }
@Override @Override
public void onProfileLookupSucceeded(final GameProfile profile) { public void onProfileLookupSucceeded(final GameProfile profile) {
UUID_CACHE.put(reportedUUID, profile.getId().toString()); UUID_CACHE.put(reportedUUID, profile.getId().toString());
if (Messaging.isDebugging()) { if (Messaging.isDebugging()) {
Messaging.debug("Fetched UUID " + profile.getId() + " for NPC " + npc.getName() Messaging.debug("Fetched UUID " + profile.getId() + " for NPC " + npc.getName()
+ " UUID " + npc.getUniqueId()); + " UUID " + npc.getUniqueId());
} }
npc.data().setPersistent(CACHED_SKIN_UUID_METADATA, profile.getId().toString()); npc.data().setPersistent(CACHED_SKIN_UUID_METADATA, profile.getId().toString());
npc.data().setPersistent(CACHED_SKIN_UUID_NAME_METADATA, profile.getName()); npc.data().setPersistent(CACHED_SKIN_UUID_NAME_METADATA, profile.getName());
} }
}); });
return npc.data().get(CACHED_SKIN_UUID_METADATA, reportedUUID); return npc.data().get(CACHED_SKIN_UUID_METADATA, reportedUUID);
} }
} }