This commit is contained in:
parent
4b25c110ee
commit
4908ea0f44
@ -1628,6 +1628,7 @@ Item tag adjustments
|
||||
Pine tree loot pool update
|
||||
DB characters store toolbar items
|
||||
Scaffolding for new macro-cognizating ai approach
|
||||
AI work
|
||||
|
||||
|
||||
|
||||
|
||||
@ -84,7 +84,6 @@ import electrosphere.server.datacell.EntityDataCellMapper;
|
||||
import electrosphere.server.datacell.RealmManager;
|
||||
import electrosphere.server.db.DatabaseController;
|
||||
import electrosphere.server.entity.poseactor.PoseModel;
|
||||
import electrosphere.server.macro.MacroData;
|
||||
import electrosphere.server.saves.Save;
|
||||
import electrosphere.server.simulation.MacroSimulation;
|
||||
import electrosphere.server.simulation.MicroSimulation;
|
||||
@ -330,7 +329,6 @@ public class Globals {
|
||||
|
||||
//macro simulation
|
||||
public static MacroSimulation macroSimulation;
|
||||
public static MacroData macroData;
|
||||
|
||||
//micro simulation
|
||||
public static MicroSimulation microSimulation;
|
||||
|
||||
@ -10,6 +10,7 @@ import com.google.gson.JsonParseException;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.server.ai.trees.test.BlockerAITree;
|
||||
import electrosphere.server.ai.trees.creature.AttackerAITree;
|
||||
import electrosphere.server.ai.trees.hierarchy.MaslowTree;
|
||||
|
||||
/**
|
||||
* Deserializes ai tree data types
|
||||
@ -20,13 +21,18 @@ public class AITreeDataSerializer implements JsonDeserializer<AITreeData> {
|
||||
public AITreeData deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
|
||||
switch(json.getAsJsonObject().get("name").getAsString()){
|
||||
case AttackerAITree.TREE_NAME:
|
||||
case AttackerAITree.TREE_NAME: {
|
||||
return context.deserialize(json, AttackerTreeData.class);
|
||||
case BlockerAITree.TREE_NAME:
|
||||
}
|
||||
case BlockerAITree.TREE_NAME: {
|
||||
return context.deserialize(json, BlockerTreeData.class);
|
||||
}
|
||||
case MaslowTree.TREE_NAME: {
|
||||
return context.deserialize(json, MaslowTreeData.class);
|
||||
}
|
||||
}
|
||||
|
||||
LoggerInterface.loggerEngine.ERROR(new IllegalArgumentException("JSON Object provided to AITreeDataSerializer that cannot deserialize into a tree data type cleanly"));
|
||||
LoggerInterface.loggerEngine.ERROR(new IllegalArgumentException("JSON Object provided to AITreeDataSerializer that cannot deserialize into a tree data type cleanly " + json.getAsJsonObject().get("name").getAsString()));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package electrosphere.game.data.creature.type.ai;
|
||||
|
||||
import electrosphere.server.ai.trees.creature.AttackerAITree;
|
||||
|
||||
/**
|
||||
* Configuration data for an attacker tree
|
||||
*/
|
||||
@ -33,7 +35,7 @@ public class AttackerTreeData implements AITreeData {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Attacker";
|
||||
return AttackerAITree.TREE_NAME;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
package electrosphere.game.data.creature.type.ai;
|
||||
|
||||
import electrosphere.server.ai.trees.test.BlockerAITree;
|
||||
|
||||
/**
|
||||
* Data for a blocker ai tree
|
||||
*/
|
||||
@ -7,7 +9,7 @@ public class BlockerTreeData implements AITreeData {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Blocker";
|
||||
return BlockerAITree.TREE_NAME;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package electrosphere.game.data.creature.type.ai;
|
||||
|
||||
import electrosphere.server.ai.trees.hierarchy.MaslowTree;
|
||||
|
||||
/**
|
||||
* Tree data for controlling a maslow tree
|
||||
*/
|
||||
public class MaslowTreeData implements AITreeData {
|
||||
|
||||
/**
|
||||
* The name of the tree
|
||||
*/
|
||||
String name;
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return MaslowTree.TREE_NAME;
|
||||
}
|
||||
|
||||
}
|
||||
@ -190,6 +190,13 @@ public class AI {
|
||||
this.applyToPlayer = applyToPlayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the blackboard for the ai
|
||||
* @return The blackboard
|
||||
*/
|
||||
public Blackboard getBlackboard(){
|
||||
return this.blackboard;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ import java.util.Random;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.game.data.creature.type.ai.AITreeData;
|
||||
import electrosphere.logger.LoggerInterface;
|
||||
import electrosphere.server.ai.services.NearbyEntityService;
|
||||
import electrosphere.server.ai.services.TimerService;
|
||||
|
||||
/**
|
||||
@ -41,6 +42,11 @@ public class AIManager {
|
||||
*/
|
||||
TimerService timerService = new TimerService();
|
||||
|
||||
/**
|
||||
* The nearby entity service
|
||||
*/
|
||||
NearbyEntityService nearbyEntityService = new NearbyEntityService();
|
||||
|
||||
/**
|
||||
* The random of the ai
|
||||
*/
|
||||
@ -131,6 +137,7 @@ public class AIManager {
|
||||
*/
|
||||
private void execServices(){
|
||||
timerService.exec();
|
||||
nearbyEntityService.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,6 +148,14 @@ public class AIManager {
|
||||
return timerService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nearby entity service
|
||||
* @return The nearby enttiy service
|
||||
*/
|
||||
public NearbyEntityService getNearbyEntityService(){
|
||||
return nearbyEntityService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ai manager's random
|
||||
* @return The random
|
||||
|
||||
@ -10,4 +10,19 @@ public class BlackboardKeys {
|
||||
*/
|
||||
public static final String MELEE_TARGET = "meleeTarget";
|
||||
|
||||
/**
|
||||
* The collection of nearby entities
|
||||
*/
|
||||
public static final String NEARBY_ENTITIES = "nearbyEntities";
|
||||
|
||||
/**
|
||||
* The target of the current action
|
||||
*/
|
||||
public static final String ENTITY_TARGET = "target";
|
||||
|
||||
/**
|
||||
* The target to move towards
|
||||
*/
|
||||
public static final String MOVE_TO_TARGET = "moveToTarget";
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,34 @@
|
||||
package electrosphere.server.ai.nodes.actions.interact;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.collision.CollisionEngine;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.plan.FindEntityTargetNode;
|
||||
|
||||
/**
|
||||
* Tries to collect an item
|
||||
*/
|
||||
public class CollectItemNode implements AITreeNode {
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard){
|
||||
if(!FindEntityTargetNode.hasTarget(blackboard)){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
Entity target = FindEntityTargetNode.getTarget(blackboard);
|
||||
Vector3d parentPos = EntityUtils.getPosition(entity);
|
||||
Vector3d targetPos = EntityUtils.getPosition(target);
|
||||
if(parentPos.distance(targetPos) > CollisionEngine.DEFAULT_INTERACT_DISTANCE){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
InventoryUtils.serverAttemptStoreItemTransform(entity, target);
|
||||
FindEntityTargetNode.setTarget(blackboard, null);
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
package electrosphere.server.ai.nodes.actions.interact;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.collision.CollisionEngine;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.plan.FindEntityTargetNode;
|
||||
import electrosphere.server.player.PlayerActions;
|
||||
|
||||
/**
|
||||
* Tries to harvest an entity
|
||||
*/
|
||||
public class HarvestNode implements AITreeNode {
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard){
|
||||
if(!FindEntityTargetNode.hasTarget(blackboard)){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
Entity target = FindEntityTargetNode.getTarget(blackboard);
|
||||
Vector3d parentPos = EntityUtils.getPosition(entity);
|
||||
Vector3d targetPos = EntityUtils.getPosition(target);
|
||||
if(parentPos.distance(targetPos) > CollisionEngine.DEFAULT_INTERACT_DISTANCE){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
PlayerActions.harvest(entity, target);
|
||||
FindEntityTargetNode.setTarget(blackboard, null);
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@ -9,7 +9,7 @@ import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.types.creature.CreatureUtils;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.actions.combat.MeleeTargetingNode;
|
||||
import electrosphere.server.ai.nodes.plan.TargetPositionNode;
|
||||
import electrosphere.util.math.SpatialMathUtils;
|
||||
|
||||
/**
|
||||
@ -17,18 +17,11 @@ import electrosphere.util.math.SpatialMathUtils;
|
||||
*/
|
||||
public class FaceTargetNode implements AITreeNode {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public FaceTargetNode(){
|
||||
}
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||
if(MeleeTargetingNode.hasTarget(blackboard)){
|
||||
Entity target = MeleeTargetingNode.getTarget(blackboard);
|
||||
if(TargetPositionNode.hasMoveToTarget(blackboard)){
|
||||
Vector3d parentPos = EntityUtils.getPosition(entity);
|
||||
Vector3d targetPos = EntityUtils.getPosition(target);
|
||||
Vector3d targetPos = TargetPositionNode.getMoveToTarget(blackboard);
|
||||
Quaterniond rotation = SpatialMathUtils.calculateRotationFromPointToPoint(parentPos, targetPos);
|
||||
EntityUtils.getRotation(entity).set(rotation);
|
||||
CreatureUtils.setFacingVector(entity, CameraEntityUtils.getFacingVec(rotation));
|
||||
|
||||
@ -5,6 +5,8 @@ import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.server.ServerCharacterData;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
import electrosphere.server.macro.MacroData;
|
||||
import electrosphere.server.macro.character.Character;
|
||||
import electrosphere.server.macro.character.CharacterUtils;
|
||||
import electrosphere.server.macro.structure.Structure;
|
||||
@ -16,8 +18,10 @@ public class HasShelter implements AITreeNode {
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||
Realm entityRealm = Globals.realmManager.getEntityRealm(entity);
|
||||
MacroData macroData = entityRealm.getServerContentManager().getMacroData();
|
||||
ServerCharacterData serverCharacterData = ServerCharacterData.getServerCharacterData(entity);
|
||||
Character character = Globals.macroData.getCharacter(serverCharacterData.getCharacterId());
|
||||
Character character = macroData.getCharacter(serverCharacterData.getCharacterId());
|
||||
Structure shelter = CharacterUtils.getShelter(character);
|
||||
if(shelter == null){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
package electrosphere.server.ai.nodes.checks.macro;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
|
||||
/**
|
||||
* Checks that macro data exists
|
||||
*/
|
||||
public class MacroDataExists implements AITreeNode {
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||
Realm entityRealm = Globals.realmManager.getEntityRealm(entity);
|
||||
if(entityRealm.getServerContentManager().getMacroData() == null){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
package electrosphere.server.ai.nodes.checks.spatial;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.plan.FindEntityTargetNode;
|
||||
|
||||
/**
|
||||
* Checks if the target is inside a given range of the entity
|
||||
*/
|
||||
public class TargetRangeCheck implements AITreeNode {
|
||||
|
||||
/**
|
||||
* The distance to succeed within
|
||||
*/
|
||||
double dist;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param dist The distance outside of which the node will fail
|
||||
*/
|
||||
public TargetRangeCheck(double dist){
|
||||
this.dist = dist;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||
if(!FindEntityTargetNode.hasTarget(blackboard)){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
Entity target = FindEntityTargetNode.getTarget(blackboard);
|
||||
Vector3d targetPos = EntityUtils.getPosition(target);
|
||||
Vector3d entPos = EntityUtils.getPosition(entity);
|
||||
|
||||
if(targetPos.distance(entPos) < this.dist){
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
} else {
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package electrosphere.server.ai.nodes.plan;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
|
||||
/**
|
||||
* A node that performs functions to try to build a structure
|
||||
*/
|
||||
public class BuildStructureNode implements AITreeNode {
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package electrosphere.server.ai.nodes.plan;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.state.block.ServerBlockTree;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.blackboard.BlackboardKeys;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
|
||||
/**
|
||||
* Finds a target given some criteria
|
||||
*/
|
||||
public class FindEntityTargetNode implements AITreeNode {
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard){
|
||||
if(ServerBlockTree.getServerBlockTree(entity) != null){
|
||||
ServerBlockTree serverBlockTree = ServerBlockTree.getServerBlockTree(entity);
|
||||
if(serverBlockTree.isIdle()){
|
||||
serverBlockTree.start();
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
} else {
|
||||
return AITreeNodeResult.RUNNING;
|
||||
}
|
||||
} else {
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the target in the blackboard
|
||||
* @param blackboard The blackboard
|
||||
* @param target The target
|
||||
*/
|
||||
public static void setTarget(Blackboard blackboard, Entity target){
|
||||
blackboard.put(BlackboardKeys.ENTITY_TARGET, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently targeted entity
|
||||
* @param blackboard The blackboard
|
||||
* @return The entity target if it exists, null otherwise
|
||||
*/
|
||||
public static Entity getTarget(Blackboard blackboard){
|
||||
return (Entity)blackboard.get(BlackboardKeys.ENTITY_TARGET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the blackboard has a currently targeted entity
|
||||
* @param blackboard The blackboard
|
||||
* @return true if it has a currently targeted entity, false otherwise
|
||||
*/
|
||||
public static boolean hasTarget(Blackboard blackboard){
|
||||
return blackboard.has(BlackboardKeys.ENTITY_TARGET);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package electrosphere.server.ai.nodes.plan;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
|
||||
/**
|
||||
* Sets the type of structure to build
|
||||
*/
|
||||
public class SetBuildGoalNode implements AITreeNode {
|
||||
|
||||
/**
|
||||
* A shelter structure type
|
||||
*/
|
||||
public static final String STRUCTURE_TYPE_SHELTER = "shelter";
|
||||
|
||||
/**
|
||||
* The type of structure
|
||||
*/
|
||||
String type;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* @param type The type to set the build goal to
|
||||
*/
|
||||
public SetBuildGoalNode(String type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard){
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package electrosphere.server.ai.nodes.plan;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.blackboard.BlackboardKeys;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
|
||||
/**
|
||||
* Sets the move-to target position to the position of the targeted entity
|
||||
*/
|
||||
public class TargetPositionNode implements AITreeNode {
|
||||
|
||||
@Override
|
||||
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard){
|
||||
if(!FindEntityTargetNode.hasTarget(blackboard)){
|
||||
return AITreeNodeResult.FAILURE;
|
||||
}
|
||||
Entity target = FindEntityTargetNode.getTarget(blackboard);
|
||||
Vector3d targetPos = EntityUtils.getPosition(target);
|
||||
TargetPositionNode.setMoveToTarget(blackboard, targetPos);
|
||||
return AITreeNodeResult.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the move-to target of the blackboard
|
||||
* @param blackboard The blackboard
|
||||
* @param position The target position
|
||||
*/
|
||||
public static void setMoveToTarget(Blackboard blackboard, Vector3d position){
|
||||
blackboard.put(BlackboardKeys.MOVE_TO_TARGET, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the move-to target of the blackboard
|
||||
* @param blackboard The blackboard
|
||||
* @return The move-to target if it exists, null otherwise
|
||||
*/
|
||||
public static Vector3d getMoveToTarget(Blackboard blackboard){
|
||||
return (Vector3d)blackboard.get(BlackboardKeys.MOVE_TO_TARGET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the blackboard has a move to target
|
||||
* @param blackboard the blackboard
|
||||
* @return true if it has a move-to target, false otherwise
|
||||
*/
|
||||
public static boolean hasMoveToTarget(Blackboard blackboard){
|
||||
return blackboard.has(BlackboardKeys.MOVE_TO_TARGET);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
package electrosphere.server.ai.services;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.server.ai.AI;
|
||||
import electrosphere.server.ai.blackboard.Blackboard;
|
||||
import electrosphere.server.ai.blackboard.BlackboardKeys;
|
||||
import electrosphere.server.datacell.Realm;
|
||||
|
||||
/**
|
||||
* Gets the entities that are near this entity
|
||||
*/
|
||||
public class NearbyEntityService implements AIService {
|
||||
|
||||
/**
|
||||
* Distance to search for nearby entities
|
||||
*/
|
||||
static final double SEARCH_DIST = 32;
|
||||
|
||||
@Override
|
||||
public void exec(){
|
||||
for(AI ai : Globals.aiManager.getAIList()){
|
||||
Entity entity = ai.getParent();
|
||||
Realm realm = Globals.realmManager.getEntityRealm(entity);
|
||||
Vector3d position = EntityUtils.getPosition(entity);
|
||||
Collection<Entity> nearbyEntities = realm.getDataCellManager().entityLookup(position, NearbyEntityService.SEARCH_DIST);
|
||||
NearbyEntityService.setNearbyEntities(ai.getBlackboard(), nearbyEntities);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nearby entities
|
||||
* @param blackboard The blackboard
|
||||
* @param entities The nearby entities
|
||||
*/
|
||||
public static void setNearbyEntities(Blackboard blackboard, Collection<Entity> entities){
|
||||
blackboard.put(BlackboardKeys.NEARBY_ENTITIES, entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the nearby entities
|
||||
* @param blackboard The blackboard
|
||||
* @return The nearby entities
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Collection<Entity> getNearbyEntities(Blackboard blackboard){
|
||||
return (Collection<Entity>)blackboard.get(BlackboardKeys.NEARBY_ENTITIES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the blackboard stores nearby entities
|
||||
* @param blackboard The blackboard
|
||||
* @return true if it stores nearby entities, false otherwise
|
||||
*/
|
||||
public static boolean hasNearbyEntities(Blackboard blackboard){
|
||||
return blackboard.has(BlackboardKeys.NEARBY_ENTITIES);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package electrosphere.server.ai.trees.creature;
|
||||
|
||||
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementRelativeFacing;
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.actions.move.FaceTargetNode;
|
||||
import electrosphere.server.ai.nodes.actions.move.MoveStartNode;
|
||||
import electrosphere.server.ai.nodes.actions.move.MoveStopNode;
|
||||
import electrosphere.server.ai.nodes.checks.spatial.TargetRangeCheck;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.RunnerNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||
import electrosphere.server.ai.nodes.plan.TargetPositionNode;
|
||||
|
||||
/**
|
||||
* Moves to a target
|
||||
*/
|
||||
public class MoveToTarget {
|
||||
|
||||
/**
|
||||
* Name of the tree
|
||||
*/
|
||||
public static final String TREE_NAME = "MoveTo";
|
||||
|
||||
/**
|
||||
* Creates a move-to-target tree
|
||||
* @param dist The target distance to be within
|
||||
* @return The root node of the move-to-target tree
|
||||
*/
|
||||
public static AITreeNode create(double dist){
|
||||
return new SelectorNode(
|
||||
new SequenceNode(
|
||||
//check if in range of target
|
||||
new TargetRangeCheck(0),
|
||||
//if in range, stop moving fowards and return SUCCESS
|
||||
new SucceederNode(new MoveStopNode())
|
||||
),
|
||||
|
||||
//not in range of target, keep moving towards it
|
||||
new SequenceNode(
|
||||
new TargetPositionNode(),
|
||||
//check that dependencies exist
|
||||
new FaceTargetNode(),
|
||||
new RunnerNode(new MoveStartNode(MovementRelativeFacing.FORWARD))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,10 @@
|
||||
package electrosphere.server.ai.trees.hierarchy;
|
||||
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.checks.macro.IsCharacterNode;
|
||||
import electrosphere.server.ai.nodes.checks.macro.MacroDataExists;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
import electrosphere.server.ai.trees.hierarchy.safety.MaslowSafetyTree;
|
||||
|
||||
/**
|
||||
@ -20,6 +23,14 @@ public class MaslowTree {
|
||||
*/
|
||||
public static AITreeNode create(){
|
||||
return new SequenceNode(
|
||||
//check that dependencies exist
|
||||
new SequenceNode(
|
||||
new PublishStatusNode("Checking dependencies for maslow tree.."),
|
||||
new MacroDataExists(),
|
||||
new IsCharacterNode()
|
||||
),
|
||||
|
||||
//check the first tier of needs
|
||||
MaslowSafetyTree.create()
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package electrosphere.server.ai.trees.hierarchy.safety;
|
||||
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||
|
||||
/**
|
||||
@ -18,7 +20,10 @@ public class CombatTree {
|
||||
* @return The root node of the tree
|
||||
*/
|
||||
public static AITreeNode create(){
|
||||
return new SucceederNode(null);
|
||||
return new SequenceNode(
|
||||
new PublishStatusNode("Engaged in mortal combat"),
|
||||
new SucceederNode(null)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package electrosphere.server.ai.trees.hierarchy.safety;
|
||||
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||
|
||||
/**
|
||||
@ -18,7 +20,10 @@ public class FleeTree {
|
||||
* @return The root node of the tree
|
||||
*/
|
||||
public static AITreeNode create(){
|
||||
return new SucceederNode(null);
|
||||
return new SequenceNode(
|
||||
new PublishStatusNode("Flee!"),
|
||||
new SucceederNode(null)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ package electrosphere.server.ai.trees.hierarchy.safety;
|
||||
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
import electrosphere.server.ai.trees.hierarchy.safety.shelter.ShelterTree;
|
||||
|
||||
/**
|
||||
@ -20,6 +21,7 @@ public class MaslowSafetyTree {
|
||||
*/
|
||||
public static AITreeNode create(){
|
||||
return new SequenceNode(
|
||||
new PublishStatusNode("Evaluate safety"),
|
||||
FleeTree.create(),
|
||||
CombatTree.create(),
|
||||
ShelterTree.create()
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
package electrosphere.server.ai.trees.hierarchy.safety.shelter;
|
||||
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
|
||||
|
||||
/**
|
||||
@ -18,6 +20,9 @@ public class ConstructShelterTree {
|
||||
* @return The root node of the tree
|
||||
*/
|
||||
public static AITreeNode create(){
|
||||
return new SucceederNode(null);
|
||||
return new SequenceNode(
|
||||
new PublishStatusNode("Construct a shelter"),
|
||||
new SucceederNode(null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import electrosphere.server.ai.nodes.checks.macro.HasShelter;
|
||||
import electrosphere.server.ai.nodes.checks.macro.IsCharacterNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
|
||||
|
||||
/**
|
||||
* A tree that causes the entity to try to secure shelter
|
||||
@ -22,6 +23,7 @@ public class ShelterTree {
|
||||
*/
|
||||
public static AITreeNode create(){
|
||||
return new SequenceNode(
|
||||
new PublishStatusNode("Evaluate shelter"),
|
||||
//make sure that this entity actually cares about shelter
|
||||
new SequenceNode(
|
||||
//if this is a character
|
||||
@ -32,13 +34,13 @@ public class ShelterTree {
|
||||
//if has shelter..
|
||||
new SelectorNode(
|
||||
new SequenceNode(
|
||||
new HasShelter(),
|
||||
//does not have shelter
|
||||
ConstructShelterTree.create()
|
||||
),
|
||||
new SequenceNode(
|
||||
new HasShelter()
|
||||
//already has shelter
|
||||
//TODO: check environment (ie time of day) to see if we should return to shelter
|
||||
),
|
||||
new SequenceNode(
|
||||
//does not have shelter
|
||||
ConstructShelterTree.create()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
package electrosphere.server.ai.trees.jobs;
|
||||
|
||||
import electrosphere.server.ai.nodes.AITreeNode;
|
||||
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
|
||||
|
||||
/**
|
||||
* A tree that attempts to forage for items
|
||||
*/
|
||||
public class ForageTree {
|
||||
|
||||
/**
|
||||
* Name of the tree
|
||||
*/
|
||||
public static final String TREE_NAME = "Forage";
|
||||
|
||||
/**
|
||||
* Creates a foraging tree
|
||||
* @return The root node of the tree
|
||||
*/
|
||||
public static AITreeNode create(){
|
||||
return new SequenceNode(
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
package electrosphere.server.datacell;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@ -7,10 +8,15 @@ import org.joml.Vector3d;
|
||||
import org.joml.Vector3i;
|
||||
|
||||
import electrosphere.engine.Globals;
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.entity.EntityUtils;
|
||||
import electrosphere.entity.scene.Scene;
|
||||
import electrosphere.net.server.player.Player;
|
||||
import electrosphere.server.datacell.interfaces.DataCellManager;
|
||||
|
||||
/**
|
||||
* A viewport data cell manager
|
||||
*/
|
||||
public class ViewportDataCellManager implements DataCellManager {
|
||||
|
||||
/**
|
||||
@ -125,5 +131,19 @@ public class ViewportDataCellManager implements DataCellManager {
|
||||
public void halt(){
|
||||
//does nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Entity> entityLookup(Vector3d pos, double radius) {
|
||||
List<Entity> rVal = new LinkedList<Entity>();
|
||||
for(Entity entity : this.serverDataCell.getScene().getEntityList()){
|
||||
// boundingSphere
|
||||
Vector3d entPos = EntityUtils.getPosition(entity);
|
||||
if(pos.distance(entPos) > radius){
|
||||
continue;
|
||||
}
|
||||
rVal.add(entity);
|
||||
}
|
||||
return rVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1123,4 +1123,18 @@ public class GriddedDataCellManager implements DataCellManager, VoxelCellManager
|
||||
LoggerInterface.loggerEngine.WARNING("Cell is ready: " + serverDataCell.isReady());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Entity> entityLookup(Vector3d pos, double radius) {
|
||||
List<Entity> rVal = new LinkedList<Entity>();
|
||||
this.loadedCellsLock.lock();
|
||||
for(ServerDataCell cell : this.groundDataCells.values()){
|
||||
if(ServerWorldData.convertChunkToRealSpace(this.getCellWorldPosition(cell)).distance(pos) > radius){
|
||||
continue;
|
||||
}
|
||||
rVal.addAll(cell.getScene().getEntityList());
|
||||
}
|
||||
this.loadedCellsLock.unlock();
|
||||
return rVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,8 +1,11 @@
|
||||
package electrosphere.server.datacell.interfaces;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3i;
|
||||
|
||||
import electrosphere.entity.Entity;
|
||||
import electrosphere.net.server.player.Player;
|
||||
import electrosphere.server.datacell.ServerDataCell;
|
||||
|
||||
@ -86,5 +89,13 @@ public interface DataCellManager {
|
||||
* Halts all asynchronous work being done in this data cell manager
|
||||
*/
|
||||
public void halt();
|
||||
|
||||
/**
|
||||
* Looks up entities within a bounding sphere
|
||||
* @param pos The position of the sphere
|
||||
* @param radius The radius of the sphere
|
||||
* @return The list of entities within the bounding sphere
|
||||
*/
|
||||
public Collection<Entity> entityLookup(Vector3d pos, double radius);
|
||||
|
||||
}
|
||||
|
||||
@ -130,11 +130,7 @@ public class PlayerActions {
|
||||
Entity playerEntity = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
|
||||
switch(signal){
|
||||
case InteractionData.ON_INTERACT_HARVEST: {
|
||||
if(ServerLifeTree.hasServerLifeTree(target)){
|
||||
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(target);
|
||||
serverLifeTree.kill();
|
||||
}
|
||||
ServerScriptUtils.fireSignalOnEntity(playerEntity, "entityInteractHarvest", target);
|
||||
PlayerActions.harvest(playerEntity, target);
|
||||
} break;
|
||||
case InteractionData.ON_INTERACT_DOOR: {
|
||||
if(ServerDoorState.hasServerDoorState(target)){
|
||||
@ -148,5 +144,18 @@ public class PlayerActions {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to harvest the target as the creature
|
||||
* @param creature The creature
|
||||
* @param target The target to harvest
|
||||
*/
|
||||
public static void harvest(Entity creature, Entity target){
|
||||
if(ServerLifeTree.hasServerLifeTree(target)){
|
||||
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(target);
|
||||
serverLifeTree.kill();
|
||||
}
|
||||
ServerScriptUtils.fireSignalOnEntity(creature, "entityInteractHarvest", target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -18,11 +18,11 @@ public class MacroSimulation {
|
||||
* Iterates the macro simulation
|
||||
*/
|
||||
public void simulate(){
|
||||
for(Character character : Globals.macroData.getAliveCharacters()){
|
||||
//do something
|
||||
MacroSimulation.checkForShelter(character);
|
||||
MacroSimulation.checkTownMembership(character);
|
||||
}
|
||||
// for(Character character : Globals.macroData.getAliveCharacters()){
|
||||
// //do something
|
||||
// MacroSimulation.checkForShelter(character);
|
||||
// MacroSimulation.checkTownMembership(character);
|
||||
// }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
Reference in New Issue
Block a user