Skip to content

Commit 88c00e4

Browse files
olijeffers0nStrokkur424
authored andcommitted
Add initial docs for Entity Pathfinders and Mob Goal API
1 parent 6074ec8 commit 88c00e4

3 files changed

Lines changed: 187 additions & 1 deletion

File tree

astro.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ export default defineConfig({
224224
{
225225
label: "Entity API",
226226
collapsed: true,
227-
items: ["paper/dev/entity-teleport", "paper/dev/display-entities"],
227+
items: ["paper/dev/entity-teleport", "paper/dev/display-entities", "paper/dev/mob-goals", "paper/dev/entity-pathfinder"],
228228
},
229229
"paper/dev/data-component-api",
230230
"paper/dev/pdc",
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
---
2+
title: Entity Pathfinder API
3+
slug: paper/dev/entity-pathfinder
4+
description: A guide to the Entity Pathfinder API.
5+
---
6+
7+
The Entity Pathfinder API is a way of controlling the movement of entities in Minecraft. It allows you to set a path
8+
for an entity to follow, such as moving to a location, or following a player.
9+
10+
## Accessing the Pathfinder
11+
12+
To access the pathfinder for a Mob, you need to call `getPathfinder()` on the Mob. This will return an instance of `Pathfinder`.
13+
14+
:::important
15+
16+
The pathfinder is only available for Mobs, not for all entities.
17+
18+
:::
19+
20+
Lets say that we have a `Cow` and we want it to move to a specific `Player`'s location. We can do this by getting the
21+
pathfinder for the cow and then setting the path to the player's location:
22+
23+
```java
24+
Cow cow = ...;
25+
Player player = ...;
26+
27+
Pathfinder pathfinder = cow.getPathfinder();
28+
// moveTo returns a boolean indicating whether the path was set successfully
29+
boolean success = pathfinder.moveTo(player.getLocation());
30+
```
31+
32+
If we want to access the current Path for the cow, we can call `getCurrentPath()` on the pathfinder:
33+
34+
```java
35+
PathResult path = pathfinder.getCurrentPath();
36+
37+
// A PathResult is essentially a wrapper around a List of Locations. These can be accessed with:
38+
List<Location> locations = path.getPoints();
39+
// It is important to note that the list contains points that have already been passed,
40+
// as well as future points. If you want to get the next point, you can use:
41+
Location nextPoint = path.getNextPoint(); // Or locations.get(path.getNextPointIndex())
42+
// Finally, you can access the final destination with:
43+
Location destination = path.getFinalPoint();
44+
```
45+
46+
## Pathfinding Rules
47+
48+
Much of the way that the Pathfinder works is dictated by the limitations of the actual entity pathfinding in Minecraft.
49+
For example, a Polar Bear cannot fly. This means that if you set a path for a Polar Bear to a location that is in the air,
50+
it will not be able to reach it.
51+
52+
There are some attributes that can be set on the pathfinder to change the way that the pathfinder works. These are:
53+
- `setCanOpenDoors(boolean)`: Whether the entity can open doors.
54+
- `setCanPassDoors(boolean)`: Whether the entity can pass through open doors.
55+
- `setCanFloat(boolean)`: Whether the entity can float in water.
56+
These all have respective getters as well.
57+
58+
## Stopping the Pathfinder
59+
60+
To stop the pathfinder, you can call `stopPathfinding()` on the pathfinder. This will stop the pathfinder and clear the
61+
current path. You can use `hasPath()` to check if the pathfinder is currently running.
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
---
2+
title: Mob Goal API
3+
slug: paper/dev/mob-goals
4+
description: A guide to the Mob Goal API.
5+
---
6+
7+
The Mob Goal API is a way of controlling the behaviour of mobs in Minecraft. It allows you to set a goal for a mob to perform, such as
8+
attacking a player, or moving to a location. It also allows you to create your own custom goals.
9+
10+
## Registering a Goal on an Entity
11+
12+
To register a goal on an entity, you need to create an instance of the goal and then register it with the entity:
13+
14+
```java
15+
Cow cow = ...;
16+
Goal<Cow> goal = new ExampleGoal();
17+
18+
server.getMobGoals().addGoal(cow, 0, goal); // 0 is the priority, lower numbers are higher priority
19+
```
20+
21+
:::tip
22+
23+
You can access the Vanilla goals from the `VanillaGoal` class. These are the goals that are used by Vanilla Minecraft.
24+
They are specific to each mob type, so you can't use a cow goal on a zombie for example.
25+
26+
:::
27+
28+
## Creating a Custom Goal
29+
30+
To create a custom goal, you need to create a class that implements the `Goal` interface. This interface has several methods:
31+
- `void start()`: Called when the goal is started.
32+
- `void tick()`: Called every tick while the goal is running.
33+
- `void stop()`: Called when the goal is stopped.
34+
- `boolean shouldActivate()`: Called to determine if the goal should start.
35+
- `boolean shouldStayActive()`: Called to determine if the goal should continue running.
36+
- `GoalKey getKey()`: Called to get the key for the goal.
37+
- `EnumSet<GoalType> getTypes()`: Called to get the types of the goal.
38+
39+
:::note[Types]
40+
41+
The `getTypes()` method is used to determine what types of goal this is. The types are:
42+
- `GoalType.MOVE`: The goal moves the entity.
43+
- `GoalType.LOOK`: The goal changes the direction the entity is looking.
44+
- `GoalType.JUMP`: The goal makes the entity jump.
45+
- `GoalType.TARGET`: The goal changes the target of the entity.
46+
- `GoalType.UNKNOWN_BEHAVIOR`: The goal does something else. Used for mapping Vanilla goals.
47+
48+
:::
49+
50+
Here is an example of a goal that makes a camel follow a player. This is essentially the same as the `FOLLOW_MOB` in Vanilla,
51+
but it is a good example of how to create a goal.
52+
53+
```java
54+
public class CamelFollowPlayerGoal implements Goal<Camel> {
55+
56+
public static final GoalKey<Camel> KEY = GoalKey.of(Camel.class, new NamespacedKey("testplugin", "camel_follow_player"));
57+
58+
private final Player player;
59+
private final Camel camel;
60+
61+
public CamelFollowPlayerGoal(Player player, Camel camel) {
62+
// The constructor takes the Player to follow and the Camel that is following
63+
this.player = player;
64+
this.camel = camel;
65+
}
66+
67+
@Override
68+
public boolean shouldActivate() {
69+
// This is whether or the goal should start. In this case, we want the goal to always start so we return true.
70+
// You could also return false here if you wanted to only start the goal in certain situations.
71+
return true;
72+
}
73+
74+
@Override
75+
public void start() {
76+
// This is called when the goal starts. In this case, we just send a message to the player.
77+
player.sendMessage(text("I am following you!"));
78+
}
79+
80+
@Override
81+
public void tick() {
82+
// This is called every tick while the goal is running. In this case, we make the camel move towards the player
83+
// using the Pathfinder API. The 5.0 is the speed of the camel.
84+
camel.getPathfinder().moveTo(player, 5.0);
85+
}
86+
87+
@Override
88+
public void stop() {
89+
// This is called when the goal stops. In this case, we just send a message to the player.
90+
player.sendMessage(text("I Stopped following you!"));
91+
}
92+
93+
@Override
94+
public @NotNull GoalKey<Camel> getKey() {
95+
// This is the key for the goal. It is used to identify the goal and is used to determine if two goals are the same.
96+
// It requires the class of the entity and a NamespacedKey. The NamespacedKey is used to identify the goal.
97+
// You should use the plugin's namespace for the NamespacedKey, not Minecraft or Bukkit.
98+
return KEY;
99+
}
100+
101+
@Override
102+
public @NotNull EnumSet<GoalType> getTypes() {
103+
// This is used to determine what types of goal this is. In this case, we are moving the entity and changing the
104+
// direction it is looking, so we return MOVE and LOOK. Return as many types as you need.
105+
return EnumSet.of(GoalType.MOVE, GoalType.LOOK);
106+
}
107+
}
108+
```
109+
110+
## Stopping a Goal
111+
112+
To stop a goal, you need to get the goal key and then call `stop()` on the goal:
113+
114+
```java
115+
Cow cow = ...;
116+
// This works because our example has a public static `KEY` field
117+
server.getMobGoals().removeGoal(cow, CamelFollowPlayerGoal.KEY);
118+
119+
// You can also remove Vanilla goals
120+
server.getMobGoals().removeGoal(cow, VanillaGoal.TEMPT);
121+
122+
// You can also remove all goals
123+
server.getMobGoals().removeAllGoals(cow);
124+
server.getMobGoals().removeAllGoals(cow, GoalType.MOVE); // Remove all MOVE goals
125+
```

0 commit comments

Comments
 (0)