move goal logic to macro sim
Some checks reported errors
studiorailgun/Renderer/pipeline/head Something is wrong with the build of this commit

This commit is contained in:
austin 2025-05-10 17:38:10 -04:00
parent c893e0568a
commit 9963c4aa78
13 changed files with 119 additions and 29 deletions

View File

@ -1706,6 +1706,7 @@ Major work on CharacterService
Move character utils classe to macro data Move character utils classe to macro data
Move CharacterService to service package Move CharacterService to service package
Convert character service to singleton Convert character service to singleton
Start moving character goal logic from behavior trees to macro level simulation

View File

@ -179,7 +179,7 @@ public class ImGuiAI {
GriddedDataCellManager griddedDataCellManager = (GriddedDataCellManager)realm.getDataCellManager(); GriddedDataCellManager griddedDataCellManager = (GriddedDataCellManager)realm.getDataCellManager();
Entity serverEnt = EntityLookupUtils.getServerEquivalent(Globals.playerEntity); Entity serverEnt = EntityLookupUtils.getServerEquivalent(Globals.playerEntity);
Vector3d spawnPos = griddedDataCellManager.getMacroEntryPoint(new Vector3d(EntityUtils.getPosition(serverEnt)).add(50,0,0)); Vector3d spawnPos = griddedDataCellManager.getMacroEntryPoint(new Vector3d(EntityUtils.getPosition(serverEnt)).add(50,0,0));
CharacterUtils.spawnCharacter(realm, spawnPos); CharacterUtils.spawnCharacter(realm, spawnPos, CharacterUtils.DEFAULT_RACE);
} }
} }

View File

@ -68,6 +68,12 @@ public class MacroCharacterGoalNode implements AITreeNode {
Vector3d targetPos = offset;//griddedDataCellManager.getMacroEntryPoint(offset).add(10,0,0); Vector3d targetPos = offset;//griddedDataCellManager.getMacroEntryPoint(offset).add(10,0,0);
blackboard.put(BlackboardKeys.POINT_TARGET, targetPos); blackboard.put(BlackboardKeys.POINT_TARGET, targetPos);
} break; } break;
case BUILD_STRUCTURE: {
throw new Error("Not implemented yet");
} //break;
case ACQUIRE_ITEM: {
throw new Error("Not implemented yet");
} //break;
} }
if(type == goal.getType()){ if(type == goal.getType()){
return AITreeNodeResult.SUCCESS; return AITreeNodeResult.SUCCESS;

View File

@ -1,15 +1,19 @@
package electrosphere.server.ai.trees.character.goals; package electrosphere.server.ai.trees.character.goals;
import electrosphere.engine.Globals;
import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementRelativeFacing; import electrosphere.entity.state.movement.groundmove.ClientGroundMovementTree.MovementRelativeFacing;
import electrosphere.server.ai.blackboard.BlackboardKeys; import electrosphere.server.ai.blackboard.BlackboardKeys;
import electrosphere.server.ai.nodes.AITreeNode; import electrosphere.server.ai.nodes.AITreeNode;
import electrosphere.server.ai.nodes.actions.move.FaceTargetNode; import electrosphere.server.ai.nodes.actions.move.FaceTargetNode;
import electrosphere.server.ai.nodes.actions.move.MoveStartNode; import electrosphere.server.ai.nodes.actions.move.MoveStartNode;
import electrosphere.server.ai.nodes.checks.spatial.BeginStructureNode;
import electrosphere.server.ai.nodes.macro.MacroCharacterGoalNode; import electrosphere.server.ai.nodes.macro.MacroCharacterGoalNode;
import electrosphere.server.ai.nodes.meta.collections.SelectorNode; import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
import electrosphere.server.ai.nodes.meta.collections.SequenceNode; import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode; import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
import electrosphere.server.ai.nodes.meta.decorators.RunnerNode; import electrosphere.server.ai.nodes.meta.decorators.RunnerNode;
import electrosphere.server.ai.trees.creature.resource.AcquireItemTree;
import electrosphere.server.ai.trees.struct.BuildStructureTree;
import electrosphere.server.macro.character.goal.CharacterGoal.CharacterGoalType; import electrosphere.server.macro.character.goal.CharacterGoal.CharacterGoalType;
/** /**
@ -30,11 +34,26 @@ public class CharacterGoalTree {
//character's goal is to leave sim range //character's goal is to leave sim range
new SequenceNode( new SequenceNode(
//check if we're trying to leave sim range
MacroCharacterGoalNode.create(CharacterGoalType.LEAVE_SIM_RANGE), MacroCharacterGoalNode.create(CharacterGoalType.LEAVE_SIM_RANGE),
new PublishStatusNode("Leaving simulation range"), new PublishStatusNode("Leaving simulation range"),
new FaceTargetNode(BlackboardKeys.POINT_TARGET), new FaceTargetNode(BlackboardKeys.POINT_TARGET),
new RunnerNode(new MoveStartNode(MovementRelativeFacing.FORWARD)) new RunnerNode(new MoveStartNode(MovementRelativeFacing.FORWARD))
),
//character's goal is to build a structure
new SequenceNode(
MacroCharacterGoalNode.create(CharacterGoalType.BUILD_STRUCTURE),
new PublishStatusNode("Construct a shelter"),
new BeginStructureNode(Globals.gameConfigCurrent.getStructureData().getTypes().iterator().next()),
BuildStructureTree.create()
),
//character's goal is to acquire an item
new SequenceNode(
MacroCharacterGoalNode.create(CharacterGoalType.ACQUIRE_ITEM),
new PublishStatusNode("Acquire building material"),
//try to find building materials
AcquireItemTree.create(BlackboardKeys.BUILDING_MATERIAL_CURRENT)
) )
) )
); );

View File

@ -1,9 +1,9 @@
package electrosphere.server.ai.trees.hierarchy.safety; package electrosphere.server.ai.trees.hierarchy.safety;
import electrosphere.server.ai.nodes.AITreeNode; import electrosphere.server.ai.nodes.AITreeNode;
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
import electrosphere.server.ai.nodes.meta.collections.SequenceNode; import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode; import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
import electrosphere.server.ai.trees.hierarchy.safety.shelter.ShelterTree;
/** /**
* A tree that runs all of the tier 1 maslow need trees * A tree that runs all of the tier 1 maslow need trees
@ -22,9 +22,10 @@ public class MaslowSafetyTree {
public static AITreeNode create(){ public static AITreeNode create(){
return new SequenceNode( return new SequenceNode(
new PublishStatusNode("Evaluate safety"), new PublishStatusNode("Evaluate safety"),
new SelectorNode(
FleeTree.create(), FleeTree.create(),
CombatTree.create(), CombatTree.create()
ShelterTree.create() )
); );
} }

View File

@ -10,10 +10,11 @@ import electrosphere.server.ai.nodes.checks.inventory.InventoryContainsNode;
import electrosphere.server.ai.nodes.meta.collections.SelectorNode; import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
import electrosphere.server.ai.nodes.meta.collections.SequenceNode; import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode; import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
import electrosphere.server.ai.nodes.meta.decorators.InverterNode;
import electrosphere.server.ai.nodes.meta.decorators.RunnerNode;
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode; import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
import electrosphere.server.ai.nodes.solvers.SolveBuildMaterialNode; import electrosphere.server.ai.nodes.solvers.SolveBuildMaterialNode;
import electrosphere.server.ai.trees.creature.MoveToTree; import electrosphere.server.ai.trees.creature.MoveToTree;
import electrosphere.server.ai.trees.creature.resource.AcquireItemTree;
/** /**
* A tree to build whatever the current structure target is * A tree to build whatever the current structure target is
@ -23,10 +24,10 @@ public class BuildStructureTree {
/** /**
* Name of the tree * Name of the tree
*/ */
public static final String TREE_NAME = "ConstructShelterTree"; public static final String TREE_NAME = "BuildStructureTree";
/** /**
* Creates a construct shelter tree * Creates a construct structure tree
* @return The root node of the tree * @return The root node of the tree
*/ */
public static AITreeNode create(){ public static AITreeNode create(){
@ -54,10 +55,10 @@ public class BuildStructureTree {
), ),
//does not have building materials //does not have building materials
new SequenceNode( new SequenceNode(
new PublishStatusNode("Acquire building material"), new InverterNode(new SolveBuildMaterialNode()),
//try to find building materials new RunnerNode(new PublishStatusNode("Waiting on macro character to set goal to find materials to build with"))
AcquireItemTree.create(BlackboardKeys.BUILDING_MATERIAL_CURRENT)
), ),
//has building materials AND we've already built the structure
new SucceederNode(null) new SucceederNode(null)
) )
); );

View File

@ -67,17 +67,17 @@ public class MacroData {
// } // }
//generate initial races //generate initial races
if(Globals.gameConfigCurrent.getRaceMap().getSymbolismMap().size() < 3){ if(Globals.gameConfigCurrent.getRaceMap().getRaces().size() < 3){
for(Race race : Globals.gameConfigCurrent.getRaceMap().getSymbolismMap()){ for(Race race : Globals.gameConfigCurrent.getRaceMap().getRaces()){
rVal.races.add(race); rVal.races.add(race);
} }
} else { } else {
RaceMap raceMap = Globals.gameConfigCurrent.getRaceMap(); RaceMap raceMap = Globals.gameConfigCurrent.getRaceMap();
int numRacesToGenerate = 3 + random.nextInt(Math.min(raceMap.getSymbolismMap().size() - 3,7)); int numRacesToGenerate = 3 + random.nextInt(Math.min(raceMap.getRaces().size() - 3,7));
for(int i = 0; i < numRacesToGenerate; i++){ for(int i = 0; i < numRacesToGenerate; i++){
Race raceToAdd = raceMap.getSymbolismMap().get(random.nextInt(raceMap.getSymbolismMap().size())); Race raceToAdd = raceMap.getRaces().get(random.nextInt(raceMap.getRaces().size()));
while(rVal.races.contains(raceToAdd)){ while(rVal.races.contains(raceToAdd)){
raceToAdd = raceMap.getSymbolismMap().get(random.nextInt(raceMap.getSymbolismMap().size())); raceToAdd = raceMap.getRaces().get(random.nextInt(raceMap.getRaces().size()));
} }
rVal.races.add(raceToAdd); rVal.races.add(raceToAdd);
} }

View File

@ -35,23 +35,45 @@ public class Character implements MacroObject {
Vector3d pos = new Vector3d(); Vector3d pos = new Vector3d();
/**
* Gets the id of the character
* @return The id of the character
*/
public int getId() { public int getId() {
return id; return id;
} }
/**
* Sets the id of the character
* @param id The id of the character
*/
public void setId(int id){ public void setId(int id){
this.id = id; this.id = id;
} }
/**
* Puts data on the character
* @param key The key for the data
* @param item The data itself
*/
public void putData(String key, CharacterData item){ public void putData(String key, CharacterData item){
data.put(key,item); data.put(key,item);
} }
/**
* Checks if the character has a type of data
* @param key The key to check
* @return true if the character has data at that key, false otherwise
*/
public boolean containsKey(String key){ public boolean containsKey(String key){
return data.containsKey(key); return data.containsKey(key);
} }
/**
* Gets the data at a given key on the character
* @param key The key
* @return The data if it exists, null otherwise
*/
public CharacterData getData(String key){ public CharacterData getData(String key){
return data.get(key); return data.get(key);
} }

View File

@ -3,6 +3,7 @@ package electrosphere.server.macro.character;
import org.joml.Vector3d; import org.joml.Vector3d;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.entity.types.creature.CreatureTemplate;
import electrosphere.server.datacell.Realm; import electrosphere.server.datacell.Realm;
import electrosphere.server.macro.character.data.CharacterDataStrings; import electrosphere.server.macro.character.data.CharacterDataStrings;
import electrosphere.server.macro.character.diety.Diety; import electrosphere.server.macro.character.diety.Diety;
@ -16,6 +17,11 @@ import electrosphere.server.service.CharacterService;
*/ */
public class CharacterUtils { public class CharacterUtils {
/**
* Default human for character stuff
*/
public static final String DEFAULT_RACE = "human";
/** /**
* Adds diety data for the character * Adds diety data for the character
* @param character The character * @param character The character
@ -53,12 +59,16 @@ public class CharacterUtils {
/** /**
* Spawns a character * Spawns a character
* @param realm The realm to spawn the character within * @param realm The realm to spawn the character within
* @param position The position to create the character at
* @param race The race of the character to create
* @return The character * @return The character
*/ */
public static Character spawnCharacter(Realm realm, Vector3d position){ public static Character spawnCharacter(Realm realm, Vector3d position, String race){
Character rVal = Globals.characterService.createCharacter(null, CharacterService.NO_PLAYER); Race raceData = Globals.gameConfigCurrent.getRaceMap().getRace(race);
String creatureType = raceData.getAssociatedCreature();
Character rVal = Globals.characterService.createCharacter(CreatureTemplate.createDefault(creatureType), CharacterService.NO_PLAYER);
rVal.setPos(position); rVal.setPos(position);
Race.setRace(rVal, Race.create("human", "human")); Race.setRace(rVal, Race.create(race, creatureType));
realm.getDataCellManager().evaluateMacroObject(rVal); realm.getDataCellManager().evaluateMacroObject(rVal);
return rVal; return rVal;
} }

View File

@ -17,6 +17,14 @@ public class CharacterGoal extends CharacterData {
* Goals is generally to leave simulation range * Goals is generally to leave simulation range
*/ */
LEAVE_SIM_RANGE, LEAVE_SIM_RANGE,
/**
* Build a structure
*/
BUILD_STRUCTURE,
/**
* Acquire an item
*/
ACQUIRE_ITEM,
} }
/** /**

View File

@ -12,12 +12,12 @@ public class Race extends CharacterData {
/** /**
* The name of the race * The name of the race
*/ */
String name; String raceId;
/** /**
* The associated creature for the race * The associated creature for the race
*/ */
String associatedCreature; String associatedCreatureId;
/** /**
* Constructor * Constructor
@ -31,7 +31,7 @@ public class Race extends CharacterData {
* @return The name of the race * @return The name of the race
*/ */
public String getName() { public String getName() {
return name; return raceId;
} }
/** /**
@ -39,7 +39,7 @@ public class Race extends CharacterData {
* @return The associated creature data * @return The associated creature data
*/ */
public String getAssociatedCreature() { public String getAssociatedCreature() {
return associatedCreature; return associatedCreatureId;
} }
/** /**
@ -50,8 +50,8 @@ public class Race extends CharacterData {
*/ */
public static Race create(String name, String creatureName){ public static Race create(String name, String creatureName){
Race race = new Race(); Race race = new Race();
race.name = name; race.raceId = name;
race.associatedCreature = creatureName; race.associatedCreatureId = creatureName;
return race; return race;
} }

View File

@ -7,10 +7,31 @@ import java.util.List;
*/ */
public class RaceMap { public class RaceMap {
/**
* The list of races
*/
List<Race> raceMap; List<Race> raceMap;
public List<Race> getSymbolismMap() { /**
* Gets the list of races
* @return The list of races
*/
public List<Race> getRaces() {
return raceMap; return raceMap;
} }
/**
* Gets race data from its name
* @param raceName The name of the race
* @return The data for the race
*/
public Race getRace(String raceName){
for(Race race : raceMap){
if(race.getName().equals(raceName)){
return race;
}
}
throw new Error("Failed to find race " + raceName);
}
} }

View File

@ -4,6 +4,7 @@ import java.util.List;
import electrosphere.engine.Globals; import electrosphere.engine.Globals;
import electrosphere.server.macro.character.Character; import electrosphere.server.macro.character.Character;
import electrosphere.server.macro.character.CharacterUtils;
import electrosphere.server.macro.character.data.CharacterDataStrings; import electrosphere.server.macro.character.data.CharacterDataStrings;
/** /**
@ -62,7 +63,7 @@ public class MacroSimulation {
If no town If no town
fashion makeshift shelter fashion makeshift shelter
*/ */
if(!chara.containsKey(CharacterDataStrings.SHELTER)){ if(CharacterUtils.getShelter(chara) != null){
// Vector2i charPos = CharacterUtils.getDiscretePosition(chara); // Vector2i charPos = CharacterUtils.getDiscretePosition(chara);
// Town nearbyTown = Town.getTownAtPosition(charPos.x,charPos.y); // Town nearbyTown = Town.getTownAtPosition(charPos.x,charPos.y);
// if(nearbyTown != null){ // if(nearbyTown != null){