mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2025-02-23 15:51:30 +01:00
Implement minecraft-like AI system
This commit is contained in:
parent
872f51afa9
commit
22979f819f
@ -1,17 +1,28 @@
|
||||
package net.citizensnpcs.npc.ai;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.citizensnpcs.api.npc.ai.AI;
|
||||
import net.citizensnpcs.api.npc.ai.Goal;
|
||||
import net.citizensnpcs.api.npc.ai.NavigationCallback;
|
||||
import net.citizensnpcs.api.npc.ai.NavigationCallback.PathCancelReason;
|
||||
import net.citizensnpcs.npc.CitizensNPC;
|
||||
import net.citizensnpcs.util.Messaging;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class CitizensAI implements AI {
|
||||
private PathStrategy executing;
|
||||
private Runnable ai;
|
||||
private boolean paused;
|
||||
private final List<NavigationCallback> callbacks = Lists.newArrayList();
|
||||
private PathStrategy executing;
|
||||
private final List<GoalEntry> executingGoals = Lists.newArrayList();
|
||||
private final List<GoalEntry> goals = Lists.newArrayList();
|
||||
private final CitizensNPC npc;
|
||||
|
||||
public CitizensAI(CitizensNPC npc) {
|
||||
@ -20,12 +31,32 @@ public class CitizensAI implements AI {
|
||||
|
||||
@Override
|
||||
public void addGoal(int priority, Goal goal) {
|
||||
// TODO Auto-generated method stub
|
||||
if (goals.contains(goal))
|
||||
return;
|
||||
goals.add(new GoalEntry(priority, goal));
|
||||
Collections.sort(goals);
|
||||
}
|
||||
|
||||
private boolean isGoalAllowable(GoalEntry test) {
|
||||
for (GoalEntry item : goals) {
|
||||
if (item == test)
|
||||
continue;
|
||||
if (test.priority >= item.priority) {
|
||||
if (executingGoals.contains(item) && !test.goal.isCompatibleWith(item.goal)) {
|
||||
return false;
|
||||
}
|
||||
} /*else if (executingGoals.contains(item) && !item.goal.requiresUpdates()) {
|
||||
return false;
|
||||
}*/
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerNavigationCallback(NavigationCallback callback) {
|
||||
if (!callbacks.contains(callback))
|
||||
callbacks.add(callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -35,16 +66,54 @@ public class CitizensAI implements AI {
|
||||
|
||||
@Override
|
||||
public void setDestination(Location destination) {
|
||||
if (executing != null) {
|
||||
Iterator<NavigationCallback> itr = callbacks.iterator();
|
||||
while (itr.hasNext()) {
|
||||
if (itr.next().onCancel(this, PathCancelReason.PLUGIN)) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
executing = new MoveStrategy(npc, destination);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTarget(LivingEntity target, boolean aggressive) {
|
||||
if (executing != null) {
|
||||
Iterator<NavigationCallback> itr = callbacks.iterator();
|
||||
while (itr.hasNext()) {
|
||||
if (itr.next().onCancel(this, PathCancelReason.PLUGIN)) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
executing = new TargetStrategy(npc, target, aggressive);
|
||||
Iterator<NavigationCallback> itr = callbacks.iterator();
|
||||
while (itr.hasNext()) {
|
||||
if (itr.next().onBegin(this)) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
paused = true;
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
paused = false;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (paused)
|
||||
return;
|
||||
if (executing != null && executing.update()) {
|
||||
Iterator<NavigationCallback> itr = callbacks.iterator();
|
||||
while (itr.hasNext()) {
|
||||
if (itr.next().onCompletion(this)) {
|
||||
itr.remove();
|
||||
}
|
||||
}
|
||||
executing = null;
|
||||
}
|
||||
|
||||
@ -56,5 +125,38 @@ public class CitizensAI implements AI {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
for (GoalEntry entry : goals) {
|
||||
boolean executing = executingGoals.contains(entry);
|
||||
|
||||
if (executing) {
|
||||
if (!entry.goal.continueExecuting() || !isGoalAllowable(entry)) {
|
||||
entry.goal.reset();
|
||||
executingGoals.remove(entry);
|
||||
}
|
||||
} else if (entry.goal.continueExecuting() && isGoalAllowable(entry)) {
|
||||
entry.goal.start();
|
||||
executingGoals.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
for (GoalEntry entry : executingGoals) {
|
||||
entry.goal.update();
|
||||
}
|
||||
}
|
||||
|
||||
private class GoalEntry implements Comparable<GoalEntry> {
|
||||
final Goal goal;
|
||||
final int priority;
|
||||
|
||||
GoalEntry(int priority, Goal goal) {
|
||||
this.priority = priority;
|
||||
this.goal = goal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(GoalEntry o) {
|
||||
return o.priority > priority ? 1 : o.priority < priority ? -1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user