First pass of /npc scoreboard

This commit is contained in:
fullwall 2014-06-27 14:16:30 -07:00
parent 18b98eb609
commit 872b5ac56f
5 changed files with 317 additions and 274 deletions

View File

@ -129,7 +129,7 @@ public class EventListen implements Listener {
toRespawn.put(coord, npc);
if (Messaging.isDebugging()) {
Messaging
.debug("Despawned id", npc.getId(), "due to chunk unload at [" + coord.x + "," + coord.z + "]");
.debug("Despawned id", npc.getId(), "due to chunk unload at [" + coord.x + "," + coord.z + "]");
}
}
}

View File

@ -79,6 +79,9 @@ import org.bukkit.entity.Player;
import org.bukkit.entity.Skeleton.SkeletonType;
import org.bukkit.entity.Villager.Profession;
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.scoreboard.DisplaySlot;
import org.bukkit.scoreboard.Objective;
import org.bukkit.scoreboard.Scoreboard;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
@ -267,7 +270,7 @@ public class NPCCommands {
}
CommandSenderCreateNPCEvent event = sender instanceof Player ? new PlayerCreateNPCEvent((Player) sender, copy)
: new CommandSenderCreateNPCEvent(sender, copy);
: new CommandSenderCreateNPCEvent(sender, copy);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
event.getNPC().destroy();
@ -343,7 +346,7 @@ public class NPCCommands {
spawnLoc = args.getSenderLocation();
}
CommandSenderCreateNPCEvent event = sender instanceof Player ? new PlayerCreateNPCEvent((Player) sender, npc)
: new CommandSenderCreateNPCEvent(sender, npc);
: new CommandSenderCreateNPCEvent(sender, npc);
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) {
npc.destroy();
@ -1018,7 +1021,7 @@ public class NPCCommands {
@Requirements(selected = true, ownership = true, types = { EntityType.CREEPER })
public void power(CommandContext args, CommandSender sender, NPC npc) {
Messaging
.sendTr(sender, npc.getTrait(Powered.class).toggle() ? Messages.POWERED_SET : Messages.POWERED_STOPPED);
.sendTr(sender, npc.getTrait(Powered.class).toggle() ? Messages.POWERED_SET : Messages.POWERED_STOPPED);
}
@Command(
@ -1109,7 +1112,40 @@ public class NPCCommands {
} else {
Messaging.sendTr(sender, Messages.RESPAWN_DELAY_DESCRIBE, npc.data().get(NPC.RESPAWN_DELAY_METADATA, -1));
}
}
@Command(
aliases = { "npc" },
usage = "scoreboard [objective] [criteria] --team [team] --score [score] --display [slot]",
desc = "Sets an NPC's scoreboard",
modifiers = { "scoreboard" },
min = 1,
max = 2,
permission = "citizens.npc.scoreboard")
@Requirements(selected = true, ownership = true, types = EntityType.PLAYER)
public void scoreboard(CommandContext args, CommandSender sender, NPC npc) {
Scoreboard main = Bukkit.getScoreboardManager().getMainScoreboard();
String objective = args.getString(0);
String criteria = args.getString(1);
Objective obj = main.getObjective(objective);
if (obj == null) {
Bukkit.getScoreboardManager().getMainScoreboard().registerNewObjective(objective, criteria);
}
Player entity = (Player) npc.getEntity();
if (args.hasValueFlag("team")) {
String team = args.getFlag("team");
if (main.getPlayerTeam(entity) != null)
main.getPlayerTeam(entity).removePlayer(entity);
if (main.getTeam(team) == null)
main.registerNewTeam(team);
main.getTeam(team).addPlayer(entity);
}
if (args.hasValueFlag("display")) {
obj.setDisplaySlot(Util.matchEnum(DisplaySlot.values(), args.getFlag("display")));
}
if (args.hasValueFlag("score")) {
obj.getScore(entity).setScore(args.getFlagInteger("score"));
}
}
@Command(

View File

@ -18,76 +18,80 @@ import org.bukkit.Location;
import org.bukkit.util.Vector;
public class AStarNavigationStrategy extends AbstractPathStrategy {
private final Location destination;
private final NPC npc;
private final NavigatorParameters params;
private Path plan;
private Vector vector;
private final int a = 0;
private final Location destination;
private final NPC npc;
private final NavigatorParameters params;
private Path plan;
AStarNavigationStrategy(NPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
this.params = params;
this.destination = dest;
this.npc = npc;
Location location = Util.getEyeLocation(npc.getEntity());
VectorGoal goal = new VectorGoal(dest, (float) params.pathDistanceMargin());
plan = ASTAR.runFully(goal, new VectorNode(goal, location, new ChunkBlockSource(location, params.range()),
params.examiners()), 50000);
if (plan == null || plan.isComplete()) {
setCancelReason(CancelReason.STUCK);
} else {
vector = plan.getCurrentVector();
if (Setting.DEBUG_PATHFINDING.asBoolean()) {
plan.debug();
}
}
}
private Vector vector;
@Override
public Location getTargetAsLocation() {
return destination;
}
AStarNavigationStrategy(NPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
this.params = params;
this.destination = dest;
this.npc = npc;
Location location = Util.getEyeLocation(npc.getEntity());
VectorGoal goal = new VectorGoal(dest, (float) params.pathDistanceMargin());
plan = ASTAR.runFully(goal, new VectorNode(goal, location, new ChunkBlockSource(location,
params.range()), params.examiners()), 50000);
if (plan == null || plan.isComplete()) {
setCancelReason(CancelReason.STUCK);
} else {
vector = plan.getCurrentVector();
if (Setting.DEBUG_PATHFINDING.asBoolean()) {
plan.debug();
}
}
}
@Override
public void stop() {
if (plan != null && Setting.DEBUG_PATHFINDING.asBoolean()) {
plan.debugEnd();
}
plan = null;
}
@Override
public Location getTargetAsLocation() {
return destination;
}
@Override
public boolean update() {
if (getCancelReason() != null || plan == null || plan.isComplete()) {
return true;
}
if (npc.getEntity().getLocation(NPC_LOCATION).toVector().distanceSquared(vector) <= params.distanceMargin()) {
plan.update(npc);
if (plan.isComplete()) {
return true;
}
vector = plan.getCurrentVector();
}
net.minecraft.server.v1_7_R3.Entity handle = NMS.getHandle(npc.getEntity());
double dX = vector.getBlockX() - handle.locX;
double dZ = vector.getBlockZ() - handle.locZ;
double dY = vector.getY() - handle.locY;
double xzDistance = dX * dX + dZ * dZ;
double distance = xzDistance + dY * dY;
if (Setting.DEBUG_PATHFINDING.asBoolean()) {
npc.getEntity().getWorld()
.playEffect(vector.toLocation(npc.getEntity().getWorld()), Effect.ENDER_SIGNAL, 0);
}
if (distance > 0 && dY > 0 && dY < 1 && xzDistance <= 2.75) {
NMS.setShouldJump(npc.getEntity());
}
double destX = vector.getX() + 0.5, destZ = vector.getZ() + 0.5;
NMS.setDestination(npc.getEntity(), destX, vector.getY(), destZ, params.speed());
params.run();
plan.run(npc);
return false;
}
@Override
public void stop() {
if (plan != null && Setting.DEBUG_PATHFINDING.asBoolean()) {
plan.debugEnd();
}
plan = null;
}
private static final AStarMachine<VectorNode, Path> ASTAR = AStarMachine.createWithDefaultStorage();
private static final Location NPC_LOCATION = new Location(null, 0, 0, 0);
}
@Override
public boolean update() {
if (getCancelReason() != null || plan == null || plan.isComplete()) {
return true;
}
if (npc.getEntity().getLocation(NPC_LOCATION).toVector().distanceSquared(vector) <= params
.distanceMargin()) {
plan.update(npc);
if (plan.isComplete()) {
return true;
}
vector = plan.getCurrentVector();
}
net.minecraft.server.v1_7_R3.Entity handle = NMS.getHandle(npc.getEntity());
double dX = vector.getBlockX() - handle.locX;
double dZ = vector.getBlockZ() - handle.locZ;
double dY = vector.getY() - handle.locY;
double xzDistance = dX * dX + dZ * dZ;
double distance = xzDistance + dY * dY;
if (Setting.DEBUG_PATHFINDING.asBoolean()) {
npc.getEntity().getWorld()
.playEffect(vector.toLocation(npc.getEntity().getWorld()), Effect.ENDER_SIGNAL, 0);
}
if (distance > 0 && dY > 0 && dY < 1 && xzDistance <= 2.75) {
NMS.setShouldJump(npc.getEntity());
}
double destX = vector.getX() + 0.5, destZ = vector.getZ() + 0.5;
NMS.setDestination(npc.getEntity(), destX, vector.getY(), destZ, params.speed());
params.run();
plan.run(npc);
return false;
}
private static final AStarMachine<VectorNode, Path> ASTAR = AStarMachine
.createWithDefaultStorage();
private static final Location NPC_LOCATION = new Location(null, 0, 0, 0);
}

View File

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

View File

@ -331,4 +331,4 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder {
private static final float EPSILON = 0.005F;
private static final Location LOADED_LOCATION = new Location(null, 0, 0, 0);
}
}