Fix player movement speed and add iterations per tick setting for new pathfinder

This commit is contained in:
fullwall 2020-05-06 18:08:12 +08:00
parent e1f749236b
commit c72016046b
6 changed files with 70 additions and 51 deletions

View File

@ -16,7 +16,7 @@
<craftbukkit.version>1.15.2-R0.1-SNAPSHOT</craftbukkit.version>
<citizensapi.version>${project.version}</citizensapi.version>
<powermock.version>1.4.12</powermock.version>
<bstats.version>1.5</bstats.version>
<bstats.version>1.7</bstats.version>
</properties>
<repositories>

View File

@ -454,7 +454,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
private void startMetrics() {
try {
Metrics metrics = new Metrics(this);
Metrics metrics = new Metrics(this, 2463);
metrics.addCustomChart(new Metrics.SingleLineChart("total_npcs", new Callable<Integer>() {
@Override
@ -464,10 +464,15 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
return Iterables.size(npcRegistry);
}
}));
// todo: Read the comment in CitizensTraitFactory.
// traitFactory.addPlotters(metrics.createGraph("traits"));
/*
TODO: not implemented yet
metrics.addCustomChart(new Metrics.MultiLineChart("traits", new Callable<Map<String, Integer>>() {
@Override
public Map<String, Integer> call() throws Exception {
return traitFactory.getTraitPlot();
}
}));
*/
} catch (Exception e) {
Messaging.logTr(Messages.METRICS_ERROR_NOTIFICATION, e.getMessage());
}

View File

@ -57,6 +57,7 @@ public class Settings {
}
public enum Setting {
ASTAR_ITERATIONS_PER_TICK("npc.pathfinding.new-finder.iterations-per-tick", 25000),
AUTH_SERVER_URL("general.authlib.profile-url", "https://sessionserver.mojang.com/session/minecraft/profile/"),
CHAT_BYSTANDERS_HEAR_TARGETED_CHAT("npc.chat.options.bystanders-hear-targeted-chat", true),
CHAT_FORMAT("npc.chat.format.no-targets", "[<npc>]: <text>"),

View File

@ -10,6 +10,7 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitFactory;
@ -103,30 +104,6 @@ public class CitizensTraitFactory implements TraitFactory {
}
}
/*
TODO: We are waiting for multiline charts in bStats to implement this
*
public void addPlotters(Graph graph) {
for (Map.Entry<String, TraitInfo> entry : registered.entrySet()) {
if (INTERNAL_TRAITS.contains(entry.getKey()) || entry.getKey() == null)
continue;
final Class<? extends Trait> traitClass = entry.getValue().getTraitClass();
graph.addPlotter(new Metrics.Plotter(entry.getKey()) {
@Override
public int getValue() {
int numberUsingTrait = 0;
for (NPC npc : CitizensAPI.getNPCRegistry()) {
if (npc.hasTrait(traitClass)) {
++numberUsingTrait;
}
}
return numberUsingTrait;
}
});
}
}
*/
private <T extends Trait> T create(TraitInfo info) {
return info.tryCreateInstance();
}
@ -167,6 +144,18 @@ public class CitizensTraitFactory implements TraitFactory {
return info == null ? null : info.getTraitClass();
}
public Map<String, Integer> getTraitPlot() {
Map<String, Integer> counts = Maps.newHashMap();
for (NPC npc : CitizensAPI.getNPCRegistry()) {
for (Trait trait : npc.getTraits()) {
if (INTERNAL_TRAITS.contains(trait.getName()))
continue;
counts.put(trait.getName(), counts.getOrDefault(trait.getName(), 0) + 1);
}
}
return counts;
}
@Override
public boolean isInternalTrait(Trait trait) {
return INTERNAL_TRAITS.contains(trait.getName());

View File

@ -28,10 +28,12 @@ import net.citizensnpcs.util.NMS;
public class AStarNavigationStrategy extends AbstractPathStrategy {
private final Location destination;
private int iterations;
private final NPC npc;
private final NavigatorParameters params;
private Path plan;
private boolean planned = false;
private AStarMachine<VectorNode, Path>.AStarState state;
private Vector vector;
public AStarNavigationStrategy(NPC npc, Iterable<Vector> path, NavigatorParameters params) {
@ -60,6 +62,27 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
return destination;
}
public void initialisePathfinder() {
params.examiner(new BlockExaminer() {
@Override
public float getCost(BlockSource source, PathPoint point) {
Vector pos = point.getVector();
Material in = source.getMaterialAt(pos);
Material above = source.getMaterialAt(pos.setY(pos.getY() + 1));
return params.avoidWater() && MinecraftBlockExaminer.isLiquid(in, above) ? 1F : 0F;
}
@Override
public PassableState isPassable(BlockSource source, PathPoint point) {
return PassableState.IGNORE;
}
});
Location location = npc.getEntity().getLocation();
VectorGoal goal = new VectorGoal(destination, (float) params.pathDistanceMargin());
state = ASTAR.getStateFor(goal,
new VectorNode(goal, location, new ChunkBlockSource(location, params.range()), params.examiners()));
}
public void setPlan(Path path) {
this.plan = path;
this.planned = true;
@ -78,38 +101,41 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
if (plan != null && params.debug()) {
plan.debugEnd();
}
state = null;
plan = null;
}
@Override
public boolean update() {
if (!planned) {
params.examiner(new BlockExaminer() {
@Override
public float getCost(BlockSource source, PathPoint point) {
Vector pos = point.getVector();
Material in = source.getMaterialAt(pos);
Material above = source.getMaterialAt(pos.setY(pos.getY() + 1));
return params.avoidWater() && MinecraftBlockExaminer.isLiquid(in, above) ? 1F : 0F;
if (state == null) {
initialisePathfinder();
}
int maxIterations = Setting.MAXIMUM_ASTAR_ITERATIONS.asInt();
int iterationsPerTick = Setting.ASTAR_ITERATIONS_PER_TICK.asInt();
Path plan = ASTAR.run(state, iterationsPerTick);
if (plan == null) {
if (state.isEmpty()) {
setCancelReason(CancelReason.STUCK);
}
@Override
public PassableState isPassable(BlockSource source, PathPoint point) {
return PassableState.IGNORE;
if (iterationsPerTick > 0 && maxIterations > 0) {
iterations += iterationsPerTick;
if (iterations > maxIterations) {
setCancelReason(CancelReason.STUCK);
}
}
});
Location location = npc.getEntity().getLocation();
VectorGoal goal = new VectorGoal(destination, (float) params.pathDistanceMargin());
setPlan(ASTAR.runFully(goal,
new VectorNode(goal, location, new ChunkBlockSource(location, params.range()), params.examiners()),
Setting.MAXIMUM_ASTAR_ITERATIONS.asInt()));
} else {
setPlan(plan);
}
}
if (getCancelReason() != null || plan == null || plan.isComplete()) {
return true;
}
Location currLoc = npc.getEntity().getLocation(NPC_LOCATION);
Vector destVector = new Vector(vector.getX() + 0.5, vector.getY(), vector.getZ() + 0.5);
/*Block block = currLoc.getWorld().getBlockAt(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
/* Proper door movement - gets stuck on corners at times
Block block = currLoc.getWorld().getBlockAt(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
if (MinecraftBlockExaminer.isDoor(block.getType())) {
Door door = (Door) block.getState().getData();
if (door.isOpen()) {

View File

@ -49,9 +49,7 @@ public class PlayerControllerMove extends ControllerMove {
this.a.yaw = a(this.a.yaw, f, 90.0F);
NMS.setHeadYaw(a.getBukkitEntity(), this.a.yaw);
AttributeInstance speed = this.a.getAttributeInstance(GenericAttributes.MOVEMENT_SPEED);
if (this.a instanceof EntitySlime) {
speed.setValue(0.3D * this.e);
}
speed.setValue(0.3D * this.e);
float movement = (float) (this.e * speed.getValue());
this.a.o(movement);
this.a.bb = movement;