mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-27 03:27:56 +01:00
Added EntityAI to facilitate AI integration with other entity types (eg FakePlayer)
This commit is contained in:
parent
137273f05f
commit
7da5550858
@ -3,6 +3,7 @@ package net.minestom.server.entity;
|
|||||||
import com.extollit.gaming.ai.path.HydrazinePathFinder;
|
import com.extollit.gaming.ai.path.HydrazinePathFinder;
|
||||||
import com.extollit.gaming.ai.path.model.IPath;
|
import com.extollit.gaming.ai.path.model.IPath;
|
||||||
import net.minestom.server.attribute.Attributes;
|
import net.minestom.server.attribute.Attributes;
|
||||||
|
import net.minestom.server.entity.ai.EntityAI;
|
||||||
import net.minestom.server.entity.ai.GoalSelector;
|
import net.minestom.server.entity.ai.GoalSelector;
|
||||||
import net.minestom.server.entity.ai.TargetSelector;
|
import net.minestom.server.entity.ai.TargetSelector;
|
||||||
import net.minestom.server.entity.pathfinding.NavigableEntity;
|
import net.minestom.server.entity.pathfinding.NavigableEntity;
|
||||||
@ -24,9 +25,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public abstract class EntityCreature extends LivingEntity implements NavigableEntity {
|
public abstract class EntityCreature extends LivingEntity implements NavigableEntity, EntityAI {
|
||||||
|
|
||||||
private int removalAnimationDelay = 1000;
|
private int removalAnimationDelay = 1000;
|
||||||
|
|
||||||
@ -82,57 +82,13 @@ public abstract class EntityCreature extends LivingEntity implements NavigableEn
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(long time) {
|
public void update(long time) {
|
||||||
|
// AI
|
||||||
if (getInstance() == null) {
|
aiTick(time);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Goal selectors
|
|
||||||
{
|
|
||||||
// Supplier used to get the next goal selector which should start
|
|
||||||
// (null if not found)
|
|
||||||
final Supplier<GoalSelector> goalSelectorSupplier = () -> {
|
|
||||||
for (GoalSelector goalSelector : goalSelectors) {
|
|
||||||
final boolean start = goalSelector.shouldStart();
|
|
||||||
if (start) {
|
|
||||||
return goalSelector;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// true if the goal selector changed this tick
|
|
||||||
boolean newGoalSelector = false;
|
|
||||||
|
|
||||||
if (currentGoalSelector == null) {
|
|
||||||
// No goal selector, get a new one
|
|
||||||
this.currentGoalSelector = goalSelectorSupplier.get();
|
|
||||||
newGoalSelector = currentGoalSelector != null;
|
|
||||||
} else {
|
|
||||||
final boolean stop = currentGoalSelector.shouldEnd();
|
|
||||||
if (stop) {
|
|
||||||
// The current goal selector stopped, find a new one
|
|
||||||
this.currentGoalSelector.end();
|
|
||||||
this.currentGoalSelector = goalSelectorSupplier.get();
|
|
||||||
newGoalSelector = currentGoalSelector != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the new goal selector
|
|
||||||
if (newGoalSelector) {
|
|
||||||
this.currentGoalSelector.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Execute tick for the current goal selector
|
|
||||||
if (currentGoalSelector != null) {
|
|
||||||
currentGoalSelector.tick(time);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Path finding
|
// Path finding
|
||||||
pathFindingTick(getAttributeValue(Attributes.MOVEMENT_SPEED));
|
pathFindingTick(getAttributeValue(Attributes.MOVEMENT_SPEED));
|
||||||
|
|
||||||
|
// Fire, item pickup, ...
|
||||||
super.update(time);
|
super.update(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,26 +198,29 @@ public abstract class EntityCreature extends LivingEntity implements NavigableEn
|
|||||||
this.removalAnimationDelay = removalAnimationDelay;
|
this.removalAnimationDelay = removalAnimationDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the goal selectors of this entity.
|
|
||||||
*
|
|
||||||
* @return a modifiable list containing the entity goal selectors
|
|
||||||
*/
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@Override
|
||||||
public List<GoalSelector> getGoalSelectors() {
|
public List<GoalSelector> getGoalSelectors() {
|
||||||
return goalSelectors;
|
return goalSelectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the target selectors of this entity.
|
|
||||||
*
|
|
||||||
* @return a modifiable list containing the entity target selectors
|
|
||||||
*/
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@Override
|
||||||
public List<TargetSelector> getTargetSelectors() {
|
public List<TargetSelector> getTargetSelectors() {
|
||||||
return targetSelectors;
|
return targetSelectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public GoalSelector getCurrentGoalSelector() {
|
||||||
|
return currentGoalSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCurrentGoalSelector(GoalSelector currentGoalSelector) {
|
||||||
|
this.currentGoalSelector = currentGoalSelector;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the entity target.
|
* Gets the entity target.
|
||||||
*
|
*
|
||||||
|
102
src/main/java/net/minestom/server/entity/ai/EntityAI.java
Normal file
102
src/main/java/net/minestom/server/entity/ai/EntityAI.java
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package net.minestom.server.entity.ai;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an entity which can contain
|
||||||
|
* {@link GoalSelector goal selectors} and {@link TargetSelector target selectors}.
|
||||||
|
*/
|
||||||
|
public interface EntityAI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the goal selectors of this entity.
|
||||||
|
*
|
||||||
|
* @return a modifiable list containing the entity goal selectors
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
List<GoalSelector> getGoalSelectors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the target selectors of this entity.
|
||||||
|
*
|
||||||
|
* @return a modifiable list containing the entity target selectors
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
List<TargetSelector> getTargetSelectors();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current entity goal selector.
|
||||||
|
*
|
||||||
|
* @return the current entity goal selector, null if not any
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
GoalSelector getCurrentGoalSelector();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the entity current goal selector.
|
||||||
|
* <p>
|
||||||
|
* Mostly unsafe since the current goal selector should normally
|
||||||
|
* be chosen during the entity tick method.
|
||||||
|
*
|
||||||
|
* @param goalSelector the new entity goal selector, null to disable it
|
||||||
|
*/
|
||||||
|
void setCurrentGoalSelector(@Nullable GoalSelector goalSelector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs an AI tick, it includes finding a new {@link GoalSelector}
|
||||||
|
* or tick the current one,
|
||||||
|
*
|
||||||
|
* @param time the tick time in milliseconds
|
||||||
|
*/
|
||||||
|
default void aiTick(long time) {
|
||||||
|
GoalSelector currentGoalSelector = getCurrentGoalSelector();
|
||||||
|
// true if the goal selector changed this tick
|
||||||
|
boolean newGoalSelector = false;
|
||||||
|
|
||||||
|
if (currentGoalSelector == null) {
|
||||||
|
// No goal selector, get a new one
|
||||||
|
currentGoalSelector = findGoal();
|
||||||
|
newGoalSelector = currentGoalSelector != null;
|
||||||
|
} else {
|
||||||
|
final boolean stop = currentGoalSelector.shouldEnd();
|
||||||
|
if (stop) {
|
||||||
|
// The current goal selector stopped, find a new one
|
||||||
|
currentGoalSelector.end();
|
||||||
|
currentGoalSelector = findGoal();
|
||||||
|
newGoalSelector = currentGoalSelector != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the new goal selector
|
||||||
|
if (newGoalSelector) {
|
||||||
|
setCurrentGoalSelector(currentGoalSelector);
|
||||||
|
currentGoalSelector.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute tick for the current goal selector
|
||||||
|
if (currentGoalSelector != null) {
|
||||||
|
currentGoalSelector.tick(time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds a new {@link GoalSelector} for the entity.
|
||||||
|
* <p>
|
||||||
|
* Uses {@link GoalSelector#shouldStart()} and return the goal selector if true.
|
||||||
|
*
|
||||||
|
* @return the goal selector found, null if not any
|
||||||
|
*/
|
||||||
|
private GoalSelector findGoal() {
|
||||||
|
for (GoalSelector goalSelector : getGoalSelectors()) {
|
||||||
|
final boolean start = goalSelector.shouldStart();
|
||||||
|
if (start) {
|
||||||
|
return goalSelector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -71,7 +71,7 @@ public class RedstonePlacementRule extends BlockPlacementRule {
|
|||||||
|
|
||||||
// TODO power
|
// TODO power
|
||||||
|
|
||||||
final String[] properties = new String[]{
|
final String[] properties = {
|
||||||
"east=" + east,
|
"east=" + east,
|
||||||
"north=" + north,
|
"north=" + north,
|
||||||
"power=" + power,
|
"power=" + power,
|
||||||
|
Loading…
Reference in New Issue
Block a user