-
-
Notifications
You must be signed in to change notification settings - Fork 148
Add initial docs for Entity Pathfinders and Mob Goal API #289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
olijeffers0n
wants to merge
6
commits into
main
Choose a base branch
from
feat/document-mob-goals
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
ea4dedc
Add initial docs for Entity Pathfinders and Mob Goal API
olijeffers0n 7274f7b
Address Comments
olijeffers0n 1c27f8f
Address Comments
olijeffers0n 82e6c4d
Merge branch 'main' into feat/document-mob-goals
olijeffers0n f4b89eb
Address Comments
olijeffers0n e759306
Replace british spelling
olijeffers0n File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--- | ||
slug: /dev/entity-pathfinder | ||
description: A guide to the Entity Pathfinder API. | ||
--- | ||
|
||
# Entity Pathfinder API | ||
|
||
The Entity Pathfinder API is a way of controlling the movement of entities in Minecraft. It allows you to set a path | ||
for an entity to follow, such as moving to a location, or following a player. | ||
|
||
## Accessing the Pathfinder | ||
|
||
To access the pathfinder for a Mob, you need to call `getPathfinder()` on the Mob. This will return an instance of `Pathfinder`. | ||
|
||
:::important | ||
|
||
The pathfinder is only available for entities that implement `Mob`. | ||
|
||
::: | ||
|
||
Let's 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 | ||
pathfinder for the cow and then setting the path to the player's location: | ||
|
||
```java | ||
Cow cow = ...; | ||
Player player = ...; | ||
|
||
Pathfinder pathfinder = cow.getPathfinder(); | ||
// moveTo returns a boolean indicating whether the path was set successfully | ||
boolean success = pathfinder.moveTo(player.getLocation()); | ||
``` | ||
|
||
If we want to access the current path for the cow, we can call `getCurrentPath()` on the pathfinder: | ||
|
||
```java | ||
PathResult path = pathfinder.getCurrentPath(); | ||
|
||
// A PathResult is essentially a wrapper around a List of Locations. These can be accessed with: | ||
List<Location> locations = path.getPoints(); | ||
// It is important to note that the list contains points that have already been passed, | ||
// as well as future points. If you want to get the next point, you can use: | ||
Location nextPoint = path.getNextPoint(); // Or locations.get(path.getNextPointIndex()) | ||
// Finally, you can access the final destination with: | ||
Location destination = path.getFinalPoint(); | ||
``` | ||
|
||
## Pathfinding Rules | ||
|
||
Much of the way that the Pathfinder works is dictated by the limitations of the actual entity pathfinding in Minecraft. | ||
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, | ||
it will not be able to reach it. | ||
|
||
Some attributes can be set on the pathfinder to change the way that the pathfinder works. These are: | ||
- `setCanOpenDoors(boolean)`: Whether the entity can open doors. This is relevant for Zombies breaking down doors, and | ||
Villagers opening doors. | ||
- `setCanPassDoors(boolean)`: Whether the entity can pass through open doors. | ||
- `setCanFloat(boolean)`: Whether the entity can float in water. | ||
These all have respective getters as well. | ||
|
||
## Stopping the Pathfinder | ||
|
||
You can call `stopPathfinding()` on the pathfinder to stop the pathfinder. This will stop the pathfinder and clear the | ||
current path. You can use `hasPath()` to check if the pathfinder is running. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
--- | ||
slug: /dev/mob-goals | ||
description: A guide to the mob goal API. | ||
--- | ||
|
||
# Mob Goal API | ||
|
||
The Mob Goal API is a way of controlling the behavior of mobs in Minecraft. It allows you to set a goal for a mob to perform, such as | ||
attacking a player, or moving to a location. It also allows you to create your own custom goals. | ||
|
||
## Registering a Goal on an Entity | ||
|
||
To register a goal on an entity, you need to create an instance of the goal and then register it with the entity: | ||
|
||
```java | ||
Cow cow = ...; | ||
Goal<Cow> goal = new ExampleGoal(); | ||
|
||
server.getMobGoals().addGoal(cow, 0, goal); // 0 is the priority, lower numbers are higher priority | ||
``` | ||
|
||
:::tip | ||
|
||
You can access the Vanilla goals from the `VanillaGoal` class. These are the goals that are used by Vanilla Minecraft. | ||
They are specific to each mob type, so you can't use `VanillaGoal.BEE_ATTACK` on a Zombie, for example. | ||
|
||
::: | ||
|
||
## Creating a Custom Goal | ||
|
||
To create a custom goal, you need to create a class that implements the `Goal` interface. This interface has several methods: | ||
- `void start()`: Called when the goal is started. | ||
- `void tick()`: Called every tick while the goal is running. | ||
- `void stop()`: Called when the goal is stopped. | ||
- `boolean shouldActivate()`: Called to determine if the goal should start. | ||
- `boolean shouldStayActive()`: Called to determine if the goal should continue running. | ||
- `GoalKey getKey()`: Called to get the key for the goal. | ||
- `EnumSet<GoalType> getTypes()`: Called to get the types of the goal. | ||
|
||
:::note[types] | ||
|
||
The `getTypes()` method is used to determine what types of goal this is. The types are: | ||
- `GoalType.MOVE`: The goal moves the entity. | ||
- `GoalType.LOOK`: The goal changes the direction the entity is looking. | ||
- `GoalType.JUMP`: The goal makes the entity jump. | ||
- `GoalType.TARGET`: The goal changes the target of the entity. | ||
- `GoalType.UNKNOWN_BEHAVIOR`: The goal does something else. Used for mapping Vanilla goals. | ||
|
||
::: | ||
|
||
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, | ||
but it is a good example of how to create a goal. | ||
|
||
```java | ||
public class CamelFollowPlayerGoal implements Goal<Camel> { | ||
|
||
public static final GoalKey<Camel> KEY = GoalKey.of(Camel.class, new NamespacedKey("testplugin", "camel_follow_player")); | ||
|
||
private final Player player; | ||
private final Camel camel; | ||
|
||
public CamelFollowPlayerGoal(Player player, Camel camel) { | ||
// The constructor takes the Player to follow and the Camel that is following | ||
this.player = player; | ||
this.camel = camel; | ||
} | ||
|
||
@Override | ||
public boolean shouldActivate() { | ||
// This is whether or the goal should start. In this case, we want the goal to always start so we return true. | ||
// You could also return false here if you wanted to only start the goal in certain situations. | ||
return true; | ||
} | ||
|
||
@Override | ||
public void start() { | ||
// This is called when the goal starts. In this case, we just send a message to the player. | ||
player.sendMessage(text("I am following you!")); | ||
} | ||
|
||
@Override | ||
public void tick() { | ||
// This is called every tick while the goal is running. In this case, we make the camel move towards the player | ||
// using the Pathfinder API. The 5.0 is the speed of the camel. | ||
camel.getPathfinder().moveTo(player, 5.0); | ||
} | ||
|
||
@Override | ||
public void stop() { | ||
// This is called when the goal stops. In this case, we just send a message to the player. | ||
player.sendMessage(text("I stopped following you!")); | ||
} | ||
|
||
@Override | ||
public GoalKey<Camel> getKey() { | ||
// 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. | ||
// It requires the class of the entity and a NamespacedKey. The NamespacedKey is used to identify the goal. | ||
// You should use the plugin's namespace for the NamespacedKey, not Minecraft or Bukkit. | ||
return KEY; | ||
} | ||
|
||
@Override | ||
public @NotNull EnumSet<GoalType> getTypes() { | ||
// This is used to determine what types of goal this is. In this case, we are moving the entity and changing the | ||
// direction it is looking, so we return MOVE and LOOK. Return as many types as you need. | ||
return EnumSet.of(GoalType.MOVE, GoalType.LOOK); | ||
} | ||
} | ||
``` | ||
|
||
## Removing a Goal | ||
|
||
To remove a goal, you need to get the goal key and then call the `removeGoal` method: | ||
|
||
```java | ||
Cow cow = ...; | ||
// This works because our example has a public static `KEY` field | ||
server.getMobGoals().removeGoal(cow, CamelFollowPlayerGoal.KEY); | ||
|
||
// You can also remove Vanilla goals | ||
server.getMobGoals().removeGoal(cow, VanillaGoal.TEMPT); | ||
|
||
// You can also remove all goals | ||
server.getMobGoals().removeAllGoals(cow); | ||
server.getMobGoals().removeAllGoals(cow, GoalType.MOVE); // Remove all MOVE goals | ||
``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.