diff --git a/src/main/java/net/citizensnpcs/api/CitizensAPI.java b/src/main/java/net/citizensnpcs/api/CitizensAPI.java index 813bcb67..ebd97867 100644 --- a/src/main/java/net/citizensnpcs/api/CitizensAPI.java +++ b/src/main/java/net/citizensnpcs/api/CitizensAPI.java @@ -56,6 +56,9 @@ public static File getDataFolder() { return getImplementation().getDataFolder(); } + /** + * @return The default NPC selector + */ public static NPCSelector getDefaultNPCSelector() { return getImplementation().getDefaultNPCSelector(); } diff --git a/src/main/java/net/citizensnpcs/api/ai/GoalController.java b/src/main/java/net/citizensnpcs/api/ai/GoalController.java index 4112f778..0fb96f7f 100644 --- a/src/main/java/net/citizensnpcs/api/ai/GoalController.java +++ b/src/main/java/net/citizensnpcs/api/ai/GoalController.java @@ -5,7 +5,9 @@ /** * Represents a collection of goals that are prioritised and executed, allowing behaviour trees via a - * {@link GoalSelector}. + * {@link GoalSelector} or by implementing {@link Behavior}. + * + * In general, using {@link Behavior} is preferred due to mapping more closely to traditional behavior trees. * * The highest priority {@link Goal} that returns true in {@link Goal#shouldExecute(GoalSelector)} is executed. Any * existing goals with a lower priority are replaced via {@link Goal#reset()}. diff --git a/src/main/java/net/citizensnpcs/api/ai/PrioritisableGoal.java b/src/main/java/net/citizensnpcs/api/ai/PrioritisableGoal.java index df426edd..017c5455 100644 --- a/src/main/java/net/citizensnpcs/api/ai/PrioritisableGoal.java +++ b/src/main/java/net/citizensnpcs/api/ai/PrioritisableGoal.java @@ -1,5 +1,8 @@ package net.citizensnpcs.api.ai; +/** + * A dynamically prioritisable {@link Goal}. + */ public interface PrioritisableGoal extends Goal { int getPriority(); } diff --git a/src/main/java/net/citizensnpcs/api/ai/SimpleGoalController.java b/src/main/java/net/citizensnpcs/api/ai/SimpleGoalController.java index 94f20e29..d24cf772 100644 --- a/src/main/java/net/citizensnpcs/api/ai/SimpleGoalController.java +++ b/src/main/java/net/citizensnpcs/api/ai/SimpleGoalController.java @@ -1,5 +1,6 @@ package net.citizensnpcs.api.ai; +import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -11,6 +12,10 @@ import net.citizensnpcs.api.ai.tree.BehaviorGoalAdapter; import net.citizensnpcs.api.ai.tree.ForwardingBehaviorGoalAdapter; +/** + * A simple {@link GoalController} implementation that stores goals as a {@link ArrayList}. It works with both + * {@link Behavior}, {@link Goal} and will also consider {@link PrioritisableGoal}s if implemented. + */ public class SimpleGoalController implements GoalController { private final List executingGoals = Lists.newArrayList(); private int executingPriority = -1; @@ -59,7 +64,8 @@ public int compareTo(GoalEntry o) { public Behavior getBehavior() { return goal instanceof Behavior ? (Behavior) goal : goal instanceof ForwardingBehaviorGoalAdapter - ? ((ForwardingBehaviorGoalAdapter) goal).getWrapped() : null; + ? ((ForwardingBehaviorGoalAdapter) goal).getWrapped() + : null; } @Override @@ -262,8 +268,9 @@ public void select(Goal goal) { @Override public void selectAdditional(Goal... goals) { - for (Goal goal : goals) + for (Goal goal : goals) { addGoalToExecution(goal); + } } } } diff --git a/src/main/java/net/citizensnpcs/api/ai/flocking/AlignmentBehavior.java b/src/main/java/net/citizensnpcs/api/ai/flocking/AlignmentBehavior.java index 787f36f3..0c375106 100644 --- a/src/main/java/net/citizensnpcs/api/ai/flocking/AlignmentBehavior.java +++ b/src/main/java/net/citizensnpcs/api/ai/flocking/AlignmentBehavior.java @@ -2,10 +2,16 @@ import java.util.Collection; -import net.citizensnpcs.api.npc.NPC; - import org.bukkit.util.Vector; +import net.citizensnpcs.api.npc.NPC; + +/** + * Implements alignment flocking with a particular weight i.e. steering a flock of NPCs in line with each other. + * + * @see https://en.wikipedia.org/wiki/Flocking_(behavior) + */ public class AlignmentBehavior implements FlockBehavior { private final double weight; diff --git a/src/main/java/net/citizensnpcs/api/ai/flocking/CohesionBehavior.java b/src/main/java/net/citizensnpcs/api/ai/flocking/CohesionBehavior.java index 665c485d..cbe3fd7f 100644 --- a/src/main/java/net/citizensnpcs/api/ai/flocking/CohesionBehavior.java +++ b/src/main/java/net/citizensnpcs/api/ai/flocking/CohesionBehavior.java @@ -7,6 +7,12 @@ import net.citizensnpcs.api.npc.NPC; +/** + * Implements cohesion flocking with a particular weight i.e. steering a flock of NPCs towards each other. + * + * @see https://en.wikipedia.org/wiki/Flocking_(behavior) + */ public class CohesionBehavior implements FlockBehavior { private final double weight; diff --git a/src/main/java/net/citizensnpcs/api/ai/flocking/FlockBehavior.java b/src/main/java/net/citizensnpcs/api/ai/flocking/FlockBehavior.java index ea9505da..e28386b6 100644 --- a/src/main/java/net/citizensnpcs/api/ai/flocking/FlockBehavior.java +++ b/src/main/java/net/citizensnpcs/api/ai/flocking/FlockBehavior.java @@ -2,10 +2,21 @@ import java.util.Collection; -import net.citizensnpcs.api.npc.NPC; - import org.bukkit.util.Vector; +import net.citizensnpcs.api.npc.NPC; + +/** + * An interface to be used with an {@link Flocker} to represent a certain type of behavior such as cohesion, alignment + * or separation. + */ public interface FlockBehavior { + /** + * Returns the displacement vector to be combined with other {@link FlockBehavior} vectors by a {@link Flocker}. + * + * @param nearby + * the set of NPCs to consider for flocking purposes + * @return the displacement {@link Vector} + */ Vector getVector(NPC npc, Collection nearby); } diff --git a/src/main/java/net/citizensnpcs/api/ai/flocking/Flocker.java b/src/main/java/net/citizensnpcs/api/ai/flocking/Flocker.java index fa999643..700ad4e8 100644 --- a/src/main/java/net/citizensnpcs/api/ai/flocking/Flocker.java +++ b/src/main/java/net/citizensnpcs/api/ai/flocking/Flocker.java @@ -7,7 +7,17 @@ import org.bukkit.util.Vector; import net.citizensnpcs.api.npc.NPC; - +import net.citizensnpcs.api.trait.Trait; + +/** + * Implements a simple flocking controller as a {@link Runnable}. This should be run every tick, for example as part of + * an overridden {@link Trait#run}. + * + * @see {@link NPCFlock} + * @see {@link FlockBehavior} + * @see https://en.wikipedia.org/wiki/Flocking_(behavior) + */ public class Flocker implements Runnable { private final List behaviors; private final NPCFlock flock; @@ -33,6 +43,12 @@ public void run() { npc.getEntity().setVelocity(npc.getEntity().getVelocity().add(base)); } + /** + * Sets the maximum length of the resultant flocking vector. + * + * @param maxForce + * the new maximum length + */ public void setMaxForce(double maxForce) { this.maxForce = maxForce; } @@ -43,7 +59,4 @@ private static Vector clip(double max, Vector vector) { } return vector; } - - public static double HIGH_INFLUENCE = 1.0 / 20.0; - public static double LOW_INFLUENCE = 1.0 / 200.0; } diff --git a/src/main/java/net/citizensnpcs/api/ai/flocking/GroupNPCFlock.java b/src/main/java/net/citizensnpcs/api/ai/flocking/GroupNPCFlock.java index 34461d45..eec3a282 100644 --- a/src/main/java/net/citizensnpcs/api/ai/flocking/GroupNPCFlock.java +++ b/src/main/java/net/citizensnpcs/api/ai/flocking/GroupNPCFlock.java @@ -8,6 +8,10 @@ import net.citizensnpcs.api.npc.NPC; +/** + * Defines a static flock of NPCs with an optional radius. If the radius is positive then NPCs will only be considered + * part of the flock if they are within the base NPC's radius currently. + */ public class GroupNPCFlock implements NPCFlock { private final List npcs; private final double radius; diff --git a/src/main/java/net/citizensnpcs/api/ai/flocking/NPCFlock.java b/src/main/java/net/citizensnpcs/api/ai/flocking/NPCFlock.java index 75c56f4e..08de7003 100644 --- a/src/main/java/net/citizensnpcs/api/ai/flocking/NPCFlock.java +++ b/src/main/java/net/citizensnpcs/api/ai/flocking/NPCFlock.java @@ -4,6 +4,15 @@ import net.citizensnpcs.api.npc.NPC; +/** + * Represents a 'flock' of NPCs to be used as input to a {@link Flocker}. + * + * @see {@link RadiusNPCFlock} + * @see {@link GroupNPCFlock} + */ public interface NPCFlock { + /** + * Returns the NPCs to be considered part of a flock. + */ public Collection getNearby(NPC npc); } diff --git a/src/main/java/net/citizensnpcs/api/ai/flocking/RadiusNPCFlock.java b/src/main/java/net/citizensnpcs/api/ai/flocking/RadiusNPCFlock.java index 3f4ff26b..84295d51 100644 --- a/src/main/java/net/citizensnpcs/api/ai/flocking/RadiusNPCFlock.java +++ b/src/main/java/net/citizensnpcs/api/ai/flocking/RadiusNPCFlock.java @@ -9,6 +9,9 @@ import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.npc.NPC; +/** + * A flock of NPCs that is not static but instead uses NPCs within a certain radius as the 'flock'. + */ public class RadiusNPCFlock implements NPCFlock { private Collection cached; private int cacheTicks = 0; @@ -19,6 +22,14 @@ public RadiusNPCFlock(double radius) { this(radius, 30); } + /** + * + * @param radius + * the radius to look for nearby NPCs, in blocks @see + * {@link Entity#getNearbyEntities(double, double, double)} + * @param maxCacheTicks + * the maximum cache ticks to cache the nearby NPC 'flock' (default 30) + */ public RadiusNPCFlock(double radius, int maxCacheTicks) { this.radius = radius; this.maxCacheTicks = maxCacheTicks; diff --git a/src/main/java/net/citizensnpcs/api/ai/flocking/SeparationBehavior.java b/src/main/java/net/citizensnpcs/api/ai/flocking/SeparationBehavior.java index 8b98d110..c9955fcb 100644 --- a/src/main/java/net/citizensnpcs/api/ai/flocking/SeparationBehavior.java +++ b/src/main/java/net/citizensnpcs/api/ai/flocking/SeparationBehavior.java @@ -6,6 +6,12 @@ import net.citizensnpcs.api.npc.NPC; +/** + * Implements separation flocking with a particular weight i.e. steering a flock of NPCs away from each other. + * + * @see https://en.wikipedia.org/wiki/Flocking_(behavior) + */ public class SeparationBehavior implements FlockBehavior { private final double decayCoef = 0.5D; private final double maxAcceleration = 2D; diff --git a/src/main/java/net/citizensnpcs/api/ai/goals/MoveToGoal.java b/src/main/java/net/citizensnpcs/api/ai/goals/MoveToGoal.java index 899f10e5..bc2f99fe 100644 --- a/src/main/java/net/citizensnpcs/api/ai/goals/MoveToGoal.java +++ b/src/main/java/net/citizensnpcs/api/ai/goals/MoveToGoal.java @@ -1,13 +1,18 @@ package net.citizensnpcs.api.ai.goals; +import org.bukkit.Location; + +import net.citizensnpcs.api.ai.Goal; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.ai.event.NavigatorCallback; +import net.citizensnpcs.api.ai.tree.Behavior; import net.citizensnpcs.api.ai.tree.BehaviorGoalAdapter; import net.citizensnpcs.api.ai.tree.BehaviorStatus; import net.citizensnpcs.api.npc.NPC; -import org.bukkit.Location; - +/** + * A sample {@link Goal}/{@link Behavior} that simply moves an {@link NPC} to a specified {@link Location}. + */ public class MoveToGoal extends BehaviorGoalAdapter { private boolean finished; private final NPC npc; diff --git a/src/main/java/net/citizensnpcs/api/ai/goals/TargetNearbyEntityGoal.java b/src/main/java/net/citizensnpcs/api/ai/goals/TargetNearbyEntityGoal.java index b6cb8456..92a140ba 100644 --- a/src/main/java/net/citizensnpcs/api/ai/goals/TargetNearbyEntityGoal.java +++ b/src/main/java/net/citizensnpcs/api/ai/goals/TargetNearbyEntityGoal.java @@ -4,15 +4,22 @@ import java.util.EnumSet; import java.util.Set; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; + +import net.citizensnpcs.api.ai.Goal; +import net.citizensnpcs.api.ai.Navigator; import net.citizensnpcs.api.ai.event.CancelReason; import net.citizensnpcs.api.ai.event.NavigatorCallback; +import net.citizensnpcs.api.ai.tree.Behavior; import net.citizensnpcs.api.ai.tree.BehaviorGoalAdapter; import net.citizensnpcs.api.ai.tree.BehaviorStatus; import net.citizensnpcs.api.npc.NPC; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; - +/** + * A sample {@link Goal}/{@link Behavior} that will target specific {@link EntityType}s within a certain radius and + * start following them using {@link Navigator#setTarget(Entity, boolean)}. + */ public class TargetNearbyEntityGoal extends BehaviorGoalAdapter { private final boolean aggressive; private boolean finished; diff --git a/src/main/java/net/citizensnpcs/api/ai/goals/WanderGoal.java b/src/main/java/net/citizensnpcs/api/ai/goals/WanderGoal.java index 2fac805c..13a8dfdb 100644 --- a/src/main/java/net/citizensnpcs/api/ai/goals/WanderGoal.java +++ b/src/main/java/net/citizensnpcs/api/ai/goals/WanderGoal.java @@ -12,13 +12,18 @@ import com.google.common.base.Supplier; import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.ai.Goal; import net.citizensnpcs.api.ai.event.NavigationCompleteEvent; +import net.citizensnpcs.api.ai.tree.Behavior; import net.citizensnpcs.api.ai.tree.BehaviorGoalAdapter; import net.citizensnpcs.api.ai.tree.BehaviorStatus; import net.citizensnpcs.api.astar.pathfinder.MinecraftBlockExaminer; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.util.cuboid.QuadTree; +/** + * A sample {@link Goal}/{@link Behavior} that will wander within a certain radius or {@link QuadTree}. + */ public class WanderGoal extends BehaviorGoalAdapter implements Listener { private final Function fallback; private boolean forceFinish; @@ -114,6 +119,21 @@ public static WanderGoal createWithNPCAndRangeAndTree(NPC npc, int xrange, int y return createWithNPCAndRangeAndTreeAndFallback(npc, xrange, yrange, tree, null); } + /** + * The full builder method. + * + * @param npc + * the NPC to wander + * @param xrange + * x/z range, in blocks + * @param yrange + * y range, in blocks + * @param tree + * an optional {@link QuadTree} supplier to allow only wandering within a certain {@link QuadTree} + * @param fallback + * an optional fallback location + * @return the built goal + */ public static WanderGoal createWithNPCAndRangeAndTreeAndFallback(NPC npc, int xrange, int yrange, Supplier tree, Function fallback) { return new WanderGoal(npc, xrange, yrange, tree, fallback); diff --git a/src/main/java/net/citizensnpcs/api/ai/speech/SpeechContext.java b/src/main/java/net/citizensnpcs/api/ai/speech/SpeechContext.java index 8e9afe35..7c5acd29 100644 --- a/src/main/java/net/citizensnpcs/api/ai/speech/SpeechContext.java +++ b/src/main/java/net/citizensnpcs/api/ai/speech/SpeechContext.java @@ -5,20 +5,19 @@ import java.util.Iterator; import java.util.List; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; + import net.citizensnpcs.api.CitizensAPI; import net.citizensnpcs.api.ai.speech.event.NPCSpeechEvent; import net.citizensnpcs.api.npc.NPC; -import org.bukkit.entity.Entity; -import org.bukkit.entity.LivingEntity; - /** * SpeechContext contains information about a {@link NPCSpeechEvent}, including the {@link Talkable} talker, recipients, * and message. - * + * */ public class SpeechContext implements Iterable { - private String message; private List recipients = Collections.emptyList(); private Talkable talker = null; @@ -54,11 +53,11 @@ public SpeechContext(String message, LivingEntity recipient) { /** * Adds a direct {@link Talkable} recipient. The {@link VocalChord} should use this information to correctly direct * the message. Note: depending on the VocalChord, this list may not be inclusive as to who gets the message. - * + * * @param talkable * Talkable entity * @return the speech context - * + * */ public SpeechContext addRecipient(Entity entity) { if (recipients.isEmpty()) @@ -75,11 +74,11 @@ public SpeechContext addRecipient(LivingEntity entity) { /** * Adds a list of {@link Talkable} recipients. The {@link VocalChord} should use this information to correctly * direct the message. Note: depending on the VocalChord, this list may not be inclusive as to who gets the message. - * + * * @param talkable * Talkable entity * @return the Tongue - * + * */ public SpeechContext addRecipients(List talkables) { if (recipients.isEmpty()) @@ -90,7 +89,7 @@ public SpeechContext addRecipients(List talkables) { /** * Gets the text message sent. - * + * */ public String getMessage() { return message; @@ -98,9 +97,9 @@ public String getMessage() { /** * Gets the talker. - * + * * @return NPC doing the talking - * + * */ public Talkable getTalker() { return talker; @@ -108,7 +107,7 @@ public Talkable getTalker() { /** * Checks if there are any recipients. If none, this {@link SpeechContext} is not targeted. - * + * * @return true if recipients are specified. */ public boolean hasRecipients() { @@ -117,9 +116,9 @@ public boolean hasRecipients() { /** * Gets direct recipients, if any. - * + * * @return recipients Iterator - * + * */ @Override public Iterator iterator() { @@ -129,10 +128,10 @@ public Iterator iterator() { /** * Sets the text message sent. Overrides text set with the constructor. - * + * * @param message * The text to send. - * + * */ public void setMessage(String message) { this.message = message; @@ -140,10 +139,10 @@ public void setMessage(String message) { /** * Sets the talker. - * + * * @param entity * NPC doing the talking - * + * */ public void setTalker(Entity entity) { this.talker = CitizensAPI.getSpeechFactory().newTalkableEntity(entity); diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/Behavior.java b/src/main/java/net/citizensnpcs/api/ai/tree/Behavior.java index 35ae1ba1..cc53e05d 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/Behavior.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/Behavior.java @@ -12,6 +12,9 @@ * * This can be represented as shouldExecute() returning true -> RUNNING -> FAILURE | SUCCESS. The graph is made up of * many {@link Selector}s and {@link Sequence}s, with the leaf nodes being concrete actions. + * + * @see https://en.wikipedia.org/wiki/Behavior_tree_(artificial_intelligence,_robotics_and_control) */ public interface Behavior { /** diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/BehaviorGoalAdapter.java b/src/main/java/net/citizensnpcs/api/ai/tree/BehaviorGoalAdapter.java index 65528c04..37f2577f 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/BehaviorGoalAdapter.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/BehaviorGoalAdapter.java @@ -4,7 +4,7 @@ import net.citizensnpcs.api.ai.GoalSelector; /** - * An adapter between {@link Goal} and {@link Behavior}, forwarding the calls correctly. + * An adapter between {@link Goal} and {@link Behavior}, forwarding the calls correctly between them. */ public abstract class BehaviorGoalAdapter implements Goal, Behavior { @Override diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/Condition.java b/src/main/java/net/citizensnpcs/api/ai/tree/Condition.java index 113a78d2..cf1e8b90 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/Condition.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/Condition.java @@ -1,5 +1,8 @@ package net.citizensnpcs.api.ai.tree; +/** + * A condition interface suitable for use in {@link Behavior}s such as {@link IfElse} or {@link Loop}. + */ public interface Condition { boolean get(); } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/Empty.java b/src/main/java/net/citizensnpcs/api/ai/tree/Empty.java index b2fdf76e..8181318c 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/Empty.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/Empty.java @@ -1,5 +1,8 @@ package net.citizensnpcs.api.ai.tree; +/** + * An empty leaf {@link Behavior}. + */ public class Empty extends BehaviorGoalAdapter { private Empty() { } diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/ForwardingBehaviorGoalAdapter.java b/src/main/java/net/citizensnpcs/api/ai/tree/ForwardingBehaviorGoalAdapter.java index 2c8b80a7..2c03791e 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/ForwardingBehaviorGoalAdapter.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/ForwardingBehaviorGoalAdapter.java @@ -1,5 +1,8 @@ package net.citizensnpcs.api.ai.tree; +/** + * Forwards all calls to a secondary {@link Behavior}. + */ public class ForwardingBehaviorGoalAdapter extends BehaviorGoalAdapter { private final Behavior behavior; diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/IfElse.java b/src/main/java/net/citizensnpcs/api/ai/tree/IfElse.java index a639a524..7ce87a6a 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/IfElse.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/IfElse.java @@ -1,5 +1,9 @@ package net.citizensnpcs.api.ai.tree; +/** + * A simple if-then-else {@link Behavior} which will execute a different {@link Behavior} depending on an + * {@link Condition} function. + */ public class IfElse extends BehaviorGoalAdapter { private final Condition condition; private Behavior executing; diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/ParallelBehavior.java b/src/main/java/net/citizensnpcs/api/ai/tree/ParallelBehavior.java index aefd16bf..27ed6821 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/ParallelBehavior.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/ParallelBehavior.java @@ -3,10 +3,9 @@ /** * A marker interface for {@link Behavior}s that indicates to any parent nodes that the behavior can be run in * parallel along with other behaviors. - * + * * Parallel behaviors will not affect the success or failure status of any composite nodes; the return * {@link BehaviorStatus} will only act as a terminal status or an indication to remove the parallel node. */ public interface ParallelBehavior { - } diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/Selector.java b/src/main/java/net/citizensnpcs/api/ai/tree/Selector.java index 827183ca..327ebe05 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/Selector.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/Selector.java @@ -9,7 +9,7 @@ /** * A selector of sub-goals, that chooses a single {@link Behavior} to execute from a list. The default selection - * function is a random selection. + * function is a random selection but this can be specified in the builder. */ public class Selector extends Composite { private Behavior executing; diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/Selectors.java b/src/main/java/net/citizensnpcs/api/ai/tree/Selectors.java index 47a1b5f4..af9a592e 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/Selectors.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/Selectors.java @@ -9,6 +9,9 @@ import com.google.common.base.Function; import com.google.common.base.Preconditions; +/** + * Static helper class for creating common {@link Selector}s. + */ public class Selectors { private Selectors() { } @@ -27,23 +30,33 @@ public Behavior apply(List input) { } } + /** + * Returns a default priority selection function that assumes the input {@link Behavior}s implement + * {@link Comparable}. + */ public static Function, Behavior> prioritySelectionFunction() { - return prioritySelectionFunction0(BEHAVIOR_COMPARATOR); - } - - private static Function, Behavior> prioritySelectionFunction0( - final Comparator comparator) { - return new PrioritySelection(comparator); + return new PrioritySelection(BEHAVIOR_COMPARATOR); } + /** + * @see {@link #prioritySelector(Comparator, Collection)} + */ public static Selector.Builder prioritySelector(Comparator comparator, Behavior... behaviors) { return prioritySelector(comparator, Arrays.asList(behaviors)); } + /** + * Builds a {@link Selector} that prioritises certain {@link Behavior}s based on a comparison function. + * + * @param comparator + * The comparison function + * @param behaviors + * The behaviors to select from + */ public static Selector.Builder prioritySelector(final Comparator comparator, Collection behaviors) { Preconditions.checkArgument(behaviors.size() > 0, "must have at least one behavior for comparison"); - return Selector.selecting(behaviors).selectionFunction(prioritySelectionFunction0(comparator)); + return Selector.selecting(behaviors).selectionFunction(new PrioritySelection(comparator)); } private static final Comparator BEHAVIOR_COMPARATOR = new Comparator() { diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/Sequence.java b/src/main/java/net/citizensnpcs/api/ai/tree/Sequence.java index e087ed03..0e5c08cc 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/Sequence.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/Sequence.java @@ -4,6 +4,9 @@ import java.util.Collection; import java.util.List; +/** + * Runs each {@link Behavior} in sequence. + */ public class Sequence extends Composite { private final boolean continueRunning; private Behavior executing; @@ -95,6 +98,10 @@ public static Sequence createRetryingSequence(Behavior... behaviors) { return createRetryingSequence(Arrays.asList(behaviors)); } + /** + * Creates a retrying sequence that will continue from the current {@link Behavior} if it returns + * {@link BehaviorStatus#FAILURE} instead of propagating the failure up to its parent. + */ public static Sequence createRetryingSequence(Collection behaviors) { return new Sequence(true, behaviors); } @@ -103,6 +110,9 @@ public static Sequence createSequence(Behavior... behaviors) { return createSequence(Arrays.asList(behaviors)); } + /** + * Creates sequence that will stop executing if the current {@link Behavior} returns {@link BehaviorStatus#FAILURE}. + */ public static Sequence createSequence(Collection behaviors) { return new Sequence(false, behaviors); } diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/StatusCoercer.java b/src/main/java/net/citizensnpcs/api/ai/tree/StatusCoercer.java index 1611f660..a9a7c835 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/StatusCoercer.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/StatusCoercer.java @@ -2,6 +2,9 @@ import com.google.common.base.Supplier; +/** + * Wraps an {@link Behavior} and returns a supplied {@link BehaviorStatus} instead of the actual status. + */ public class StatusCoercer extends BehaviorGoalAdapter { private final Supplier to; private final Behavior wrapping; diff --git a/src/main/java/net/citizensnpcs/api/ai/tree/TimerDecorator.java b/src/main/java/net/citizensnpcs/api/ai/tree/TimerDecorator.java index 85c75479..567f2e48 100644 --- a/src/main/java/net/citizensnpcs/api/ai/tree/TimerDecorator.java +++ b/src/main/java/net/citizensnpcs/api/ai/tree/TimerDecorator.java @@ -1,5 +1,9 @@ package net.citizensnpcs.api.ai.tree; +/** + * Wraps a {@link Behavior} and enforces a tick limit, after which it will return {@link BehaviorStatus#FAILURE} and + * reset the child {@link Behavior}. + */ public class TimerDecorator extends BehaviorGoalAdapter { private final int limit; private int ticks; @@ -18,9 +22,9 @@ public void reset() { @Override public BehaviorStatus run() { - ticks++; - if (ticks >= limit) + if (++ticks >= limit) { return BehaviorStatus.FAILURE; + } return wrapping.run(); } diff --git a/src/main/java/net/citizensnpcs/api/astar/AStarStorage.java b/src/main/java/net/citizensnpcs/api/astar/AStarStorage.java index 284c81e8..39488e7e 100644 --- a/src/main/java/net/citizensnpcs/api/astar/AStarStorage.java +++ b/src/main/java/net/citizensnpcs/api/astar/AStarStorage.java @@ -1,13 +1,33 @@ package net.citizensnpcs.api.astar; +/** + * The storage for an {@link AStarMachine}. Controls the open and closed sets. + */ public interface AStarStorage { + /** + * Close a given {@link AStarNode}, moving it from the open set to the closed set. + */ void close(AStarNode node); + /** + * @return The {@link AStarNode} to examine next from the frontier + */ AStarNode getBestNode(); + /** + * Close a given {@link AStarNode}, moving or adding it from the frontier to the open set. + */ void open(AStarNode node); + /** + * Returns the best node from the frontier and removes it. + * + * @return The {@link AStarNode} to examine next from the frontier + */ AStarNode removeBestNode(); + /** + * Returns whether to examine a given {@link AStarNode}. + */ boolean shouldExamine(AStarNode neighbour); } diff --git a/src/main/java/net/citizensnpcs/api/astar/Agent.java b/src/main/java/net/citizensnpcs/api/astar/Agent.java index 36d4eae7..25935912 100644 --- a/src/main/java/net/citizensnpcs/api/astar/Agent.java +++ b/src/main/java/net/citizensnpcs/api/astar/Agent.java @@ -1,4 +1,7 @@ package net.citizensnpcs.api.astar; +/** + * An abstract agent that will complete a {@link Plan} as returned by {@link AStarGoal}. + */ public interface Agent { } diff --git a/src/main/java/net/citizensnpcs/api/astar/Plan.java b/src/main/java/net/citizensnpcs/api/astar/Plan.java index 47b44a9d..3df7e480 100644 --- a/src/main/java/net/citizensnpcs/api/astar/Plan.java +++ b/src/main/java/net/citizensnpcs/api/astar/Plan.java @@ -1,7 +1,13 @@ package net.citizensnpcs.api.astar; +/** + * An abstract plan returned by the {@link AStarGoal} that should be run until completion. + */ public interface Plan { boolean isComplete(); + /** + * Updates the plan. Should be run ideally every tick. + */ void update(Agent agent); } diff --git a/src/main/java/net/citizensnpcs/api/astar/SimpleAStarStorage.java b/src/main/java/net/citizensnpcs/api/astar/SimpleAStarStorage.java index 8c4a0d1d..440670a3 100644 --- a/src/main/java/net/citizensnpcs/api/astar/SimpleAStarStorage.java +++ b/src/main/java/net/citizensnpcs/api/astar/SimpleAStarStorage.java @@ -1,5 +1,6 @@ package net.citizensnpcs.api.astar; +import java.util.HashMap; import java.util.Map; import java.util.PriorityQueue; import java.util.Queue; @@ -7,6 +8,10 @@ import com.google.common.base.Supplier; import com.google.common.collect.Maps; +/** + * A base implementation of {@link AStarStorage} that uses a {@link PriorityQueue} for the frontier and {@link HashMap}s + * for the open/closed sets. + */ public class SimpleAStarStorage implements AStarStorage { private final Map closed = Maps.newHashMap(); private final Map open = Maps.newHashMap(); diff --git a/src/main/java/net/citizensnpcs/api/npc/BlockBreaker.java b/src/main/java/net/citizensnpcs/api/npc/BlockBreaker.java index f9fcd06a..9ad1081c 100644 --- a/src/main/java/net/citizensnpcs/api/npc/BlockBreaker.java +++ b/src/main/java/net/citizensnpcs/api/npc/BlockBreaker.java @@ -1,7 +1,18 @@ package net.citizensnpcs.api.npc; +import org.bukkit.entity.Player; + +import net.citizensnpcs.api.ai.tree.Behavior; import net.citizensnpcs.api.ai.tree.BehaviorGoalAdapter; +/** + * A {@link Runnable} task that will break a block over time just as a normal Minecraft {@link Player} would. Should be + * run every tick until completed. + * + * This class also implements the {@link Behavior} interface for ease of use. + * + * Due to NMS constraints, this is currently implemented inside Citizens2. + */ public abstract class BlockBreaker extends BehaviorGoalAdapter { public static class BlockBreakerConfiguration { private Runnable callback; @@ -13,6 +24,10 @@ public float blockStrengthModifier() { return modifier; } + /** + * @param modifier + * The block strength modifier + */ public BlockBreakerConfiguration blockStrengthModifier(float modifier) { this.modifier = modifier; return this; @@ -22,6 +37,10 @@ public Runnable callback() { return callback; } + /** + * @param callback + * A callback that is run on completion + */ public BlockBreakerConfiguration callback(Runnable callback) { this.callback = callback; return this; @@ -31,11 +50,21 @@ public org.bukkit.inventory.ItemStack item() { return itemStack; } + /** + * + * @param stack + * The item to simulate the NPC using to break the block (e.g. an axe for wood) + */ public BlockBreakerConfiguration item(org.bukkit.inventory.ItemStack stack) { itemStack = stack; return this; } + /** + * @param radius + * The maximum radius to be from the target block. The NPC will attempt to pathfind towards the + * target block if this is specified and it is outside of the radius. + */ public BlockBreakerConfiguration radius(double radius) { this.radius = radius; return this; diff --git a/src/main/java/net/citizensnpcs/api/npc/MetadataStore.java b/src/main/java/net/citizensnpcs/api/npc/MetadataStore.java index df59953d..10b1f07d 100644 --- a/src/main/java/net/citizensnpcs/api/npc/MetadataStore.java +++ b/src/main/java/net/citizensnpcs/api/npc/MetadataStore.java @@ -3,12 +3,12 @@ import net.citizensnpcs.api.util.DataKey; /** - * Represents a metadata + * Represents a storage system for metadata */ public interface MetadataStore { /** * Fetches metadata from the given key. - * + * * @param key * The key to get metadata from * @return The metadata at the given key, or null if not found @@ -18,7 +18,7 @@ public interface MetadataStore { /** * Fetches metadata from the given key. Sets the default value provided via {@link #set(String, Object) if the * metadata is not already stored. - * + * * @param key * The key to get metadata from * @param def @@ -29,7 +29,7 @@ public interface MetadataStore { /** * Returns whether the metadata exists. - * + * * @param key * The metadata key * @return Whether the metadata exists @@ -38,7 +38,7 @@ public interface MetadataStore { /** * Loads persistent metadata from the given {@link DataKey}. - * + * * @param key * The key to load from */ @@ -46,7 +46,7 @@ public interface MetadataStore { /** * Removes any metadata at the given metadata key. - * + * * @param key * The metadata key */ @@ -54,7 +54,7 @@ public interface MetadataStore { /** * Saves persistent metadata to the given {@link DataKey}. - * + * * @param key * The key to save to. */ @@ -62,7 +62,7 @@ public interface MetadataStore { /** * Stores data at the given key. Data will not persist. - * + * * @param key * The metadata key * @param data @@ -72,7 +72,7 @@ public interface MetadataStore { /** * Stores data at the given key. Data will persist and must be a primitive type or {@link String}. - * + * * @param key * The metadata key * @param data diff --git a/src/main/java/net/citizensnpcs/api/npc/NPC.java b/src/main/java/net/citizensnpcs/api/npc/NPC.java index 2faaa998..e833fc42 100644 --- a/src/main/java/net/citizensnpcs/api/npc/NPC.java +++ b/src/main/java/net/citizensnpcs/api/npc/NPC.java @@ -2,10 +2,12 @@ import java.util.UUID; +import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Minecart; import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause; import net.citizensnpcs.api.ai.GoalController; @@ -288,31 +290,113 @@ public interface NPC extends Agent, Cloneable { */ public void teleport(Location location, TeleportCause cause); + /** + * The Minecraft ambient sound played. String - Minecraft sound name + */ public static final String AMBIENT_SOUND_METADATA = "ambient-sound"; + /** + * Whether the NPC is collidable with Players or not. Boolean. + */ public static final String COLLIDABLE_METADATA = "collidable"; + /** + * Whether the NPC can damage other Entities. Boolean. + */ public static final String DAMAGE_OTHERS_METADATA = "damage-others"; + /** + * The Minecraft sound played when the NPC dies. String - Minecraft sound name. + */ public static final String DEATH_SOUND_METADATA = "death-sound"; + /** + * Whether the NPC is 'protected' i.e. invulnerable to damage. Boolean. + */ public static final String DEFAULT_PROTECTED_METADATA = "protected"; + /** + * Whether the NPC drops its inventory after death. Boolean. + */ public static final String DROPS_ITEMS_METADATA = "drops-items"; + /** + * Whether the NPC is 'flyable' i.e. will fly when pathfinding. Boolean. + */ public static final String FLYABLE_METADATA = "flyable"; + /** + * The color to glow using Minecraft's scoreboard glowing feature. Should be a {@link ChatColor#name()} + */ public static final String GLOWING_COLOR_METADATA = "glowing-color"; + /** + * Whether the NPC is currently glowing. Boolean. + */ public static final String GLOWING_METADATA = "glowing"; + /** + * The Minecraft sound to play when hurt. String - Minecraft sound name. + */ public static final String HURT_SOUND_METADATA = "hurt-sound"; + /** + * The Item data. Byte. + */ public static final String ITEM_DATA_METADATA = "item-type-data"; + /** + * The Item ID. Integer. + */ public static final String ITEM_ID_METADATA = "item-type-id"; + /** + * Whether the NPC is leashable. Boolean. + */ public static final String LEASH_PROTECTED_METADATA = "protected-leash"; + /** + * The Minecart item data. Byte. + */ public static final String MINECART_ITEM_DATA_METADATA = "minecart-item-data"; + /** + * The Minecart item name. + */ public static final String MINECART_ITEM_METADATA = "minecart-item-name"; + /** + * The Minecart item offset as defined by Minecraft. {@link Minecart#setDisplayBlockOffset(int)} + */ public static final String MINECART_OFFSET_METADATA = "minecart-item-offset"; + /** + * Whether the NPC's nameplate should be visible. Boolean. + */ public static final String NAMEPLATE_VISIBLE_METADATA = "nameplate-visible"; + /** + * @see {@link Skinnable} + */ public static final String PLAYER_SKIN_TEXTURE_PROPERTIES_METADATA = "player-skin-textures"; + /** + * @see {@link Skinnable} + */ public static final String PLAYER_SKIN_TEXTURE_PROPERTIES_SIGN_METADATA = "player-skin-signature"; + /** + * @see {@link Skinnable} + */ public static final String PLAYER_SKIN_USE_LATEST = "player-skin-use-latest-skin"; + /** + * @see {@link Skinnable} + */ public static final String PLAYER_SKIN_UUID_METADATA = "player-skin-name"; + /** + * The Integer delay to respawn in ticks after death. Only works if non-zero. + */ public static final String RESPAWN_DELAY_METADATA = "respawn-delay"; + /** + * The fake NPC scoreboard team name because Minecraft requires a team name. Usually will be a random UUID in String + * form. + */ public static final String SCOREBOARD_FAKE_TEAM_NAME_METADATA = "fake-scoreboard-team-name"; + /** + * Whether to save / persist across server restarts. Boolean. + */ public static final String SHOULD_SAVE_METADATA = "should-save"; + /** + * Whether to suppress sounds. Boolean. + */ public static final String SILENT_METADATA = "silent-sounds"; + /** + * Whether to allow swimming. Boolean. + */ public static final String SWIMMING_METADATA = "swim"; + /** + * Whether to prevent NPC being targeted by hostile mobs. Boolean. + */ public static final String TARGETABLE_METADATA = "protected-target"; } \ No newline at end of file diff --git a/src/main/java/net/citizensnpcs/api/npc/NPCSelector.java b/src/main/java/net/citizensnpcs/api/npc/NPCSelector.java index 6b258fe6..859057ed 100644 --- a/src/main/java/net/citizensnpcs/api/npc/NPCSelector.java +++ b/src/main/java/net/citizensnpcs/api/npc/NPCSelector.java @@ -2,6 +2,10 @@ import org.bukkit.command.CommandSender; +/** + * Manages the 'selected {@link NPC}' for the server. {@link NPC}s can be selected using selection-item specified in the + * config or via commands. + */ public interface NPCSelector { NPC getSelected(CommandSender sender); } diff --git a/src/main/java/net/citizensnpcs/api/persistence/DelegatePersistence.java b/src/main/java/net/citizensnpcs/api/persistence/DelegatePersistence.java index 170315f0..750bc392 100644 --- a/src/main/java/net/citizensnpcs/api/persistence/DelegatePersistence.java +++ b/src/main/java/net/citizensnpcs/api/persistence/DelegatePersistence.java @@ -7,9 +7,9 @@ /** * Delegates persistence to a given {@link Persister}, which will be used to create and save instances. - * - * @see Persist - * @see Persister + * + * @see {@link Persist} + * @see {@link Persister} */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) diff --git a/src/main/java/net/citizensnpcs/api/persistence/Persistable.java b/src/main/java/net/citizensnpcs/api/persistence/Persistable.java index eb39fbf9..7d4415e9 100644 --- a/src/main/java/net/citizensnpcs/api/persistence/Persistable.java +++ b/src/main/java/net/citizensnpcs/api/persistence/Persistable.java @@ -2,6 +2,11 @@ import net.citizensnpcs.api.util.DataKey; +/** + * A persistable instance that can be saved and loaded using {@link DataKey} + * + * @see PersistenceLoader#registerPersistDelegate(Class, Class) + */ public interface Persistable { public void load(DataKey root); diff --git a/src/main/java/net/citizensnpcs/api/persistence/PersistenceLoader.java b/src/main/java/net/citizensnpcs/api/persistence/PersistenceLoader.java index fd064d5d..386349a0 100644 --- a/src/main/java/net/citizensnpcs/api/persistence/PersistenceLoader.java +++ b/src/main/java/net/citizensnpcs/api/persistence/PersistenceLoader.java @@ -23,6 +23,12 @@ import net.citizensnpcs.api.util.DataKey; +/** + * The main registry for managing reflective, recursive {@link NPC} persistence. + * + * @see {@link Persist} + * @see #registerPersistDelegate(Class, Class) + */ public class PersistenceLoader { private static class PersistField { private final Persister delegate; @@ -120,7 +126,8 @@ private static void deserialise(PersistField field, DataKey root) throws Excepti set = EnumSet.noneOf((Class) field.getType()); } else { set = (Set) (field.get() != null && Set.class.isAssignableFrom(field.get().getClass()) - ? field.get().getClass().newInstance() : Sets.newHashSet()); + ? field.get().getClass().newInstance() + : Sets.newHashSet()); } } Object raw = root.getRaw(field.key); diff --git a/src/main/java/net/citizensnpcs/api/trait/Trait.java b/src/main/java/net/citizensnpcs/api/trait/Trait.java index 32fcdc1a..4e69877a 100644 --- a/src/main/java/net/citizensnpcs/api/trait/Trait.java +++ b/src/main/java/net/citizensnpcs/api/trait/Trait.java @@ -7,7 +7,10 @@ import net.citizensnpcs.api.util.DataKey; /** - * Represents a Trait that can be loaded and saved. + * Represents a Trait linked to an {@link NPC} that can be loaded and saved. This will be kept persisted inside a + * {@link NPC} across server restarts. Traits must be registered in Citizens' {@link TraitFactory}. + * + * All traits should have a default constructor with no arguments for persistence purposes. */ public abstract class Trait implements Listener, Runnable { private final String name; @@ -88,6 +91,9 @@ public void onRemove() { public void onSpawn() { } + /** + * Called every tick if overridden. + */ @Override public void run() { runImplemented = false; diff --git a/src/main/java/net/citizensnpcs/api/trait/TraitFactory.java b/src/main/java/net/citizensnpcs/api/trait/TraitFactory.java index 894a42f2..f22bc435 100644 --- a/src/main/java/net/citizensnpcs/api/trait/TraitFactory.java +++ b/src/main/java/net/citizensnpcs/api/trait/TraitFactory.java @@ -3,7 +3,6 @@ import net.citizensnpcs.api.npc.NPC; public interface TraitFactory { - /** * Adds all default traits to a given NPC. * diff --git a/src/main/java/net/citizensnpcs/api/trait/TraitName.java b/src/main/java/net/citizensnpcs/api/trait/TraitName.java index 88979f6a..6177c8a4 100644 --- a/src/main/java/net/citizensnpcs/api/trait/TraitName.java +++ b/src/main/java/net/citizensnpcs/api/trait/TraitName.java @@ -5,6 +5,10 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * A helper annotation to specify trait name for {@link TraitInfo}. Should be placed on the class implementing + * {@link Trait}. + */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface TraitName { diff --git a/src/main/java/net/citizensnpcs/api/trait/trait/Equipment.java b/src/main/java/net/citizensnpcs/api/trait/trait/Equipment.java index b5e4a149..82f561ae 100644 --- a/src/main/java/net/citizensnpcs/api/trait/trait/Equipment.java +++ b/src/main/java/net/citizensnpcs/api/trait/trait/Equipment.java @@ -19,7 +19,7 @@ import net.citizensnpcs.api.util.ItemStorage; /** - * Represents an NPC's equipment. This only is applicable to human and enderman NPCs. + * Represents an NPC's equipment. */ @TraitName("equipment") public class Equipment extends Trait { diff --git a/src/main/java/net/citizensnpcs/api/util/DataKey.java b/src/main/java/net/citizensnpcs/api/util/DataKey.java index 22fac2ca..2c0ed8c0 100644 --- a/src/main/java/net/citizensnpcs/api/util/DataKey.java +++ b/src/main/java/net/citizensnpcs/api/util/DataKey.java @@ -2,9 +2,14 @@ import java.util.Map; +import org.bukkit.configuration.ConfigurationSection; + import com.google.common.base.Predicate; import com.google.common.collect.Iterables; +/** + * A hierarchical abstract storage class. Similar to Bukkit's {@link ConfigurationSection}. + */ public abstract class DataKey { protected final String path;