ai work
All checks were successful
studiorailgun/Renderer/pipeline/head This commit looks good

This commit is contained in:
austin 2025-05-02 12:15:21 -04:00
parent af0e30dd95
commit a8a524327c
18 changed files with 289 additions and 31 deletions

View File

@ -15,6 +15,22 @@
"count": 1
}
]
},
{
"displayName": "Fantasy Brick",
"craftingTag" : "HAND",
"ingredients": [
{
"itemType": "mat:Log",
"count": 1
}
],
"products": [
{
"itemType": "block:brick_fant",
"count": 1
}
]
}
],
"files": [

View File

@ -1631,7 +1631,7 @@ Scaffolding for new macro-cognizating ai approach
AI work
(05/01/2025)
Many new AI trees
Many new AI behaviors
- AI can seek out items
- AI can harvest entities
- AI can pick up items
@ -1639,6 +1639,12 @@ Many new AI trees
- AI can equip tools
- AI can fell trees
(05/02/2025)
New AI behaviors
- Place block
- Build structure
- Stops targeting trees if they're dead

View File

@ -78,7 +78,7 @@ public class ItemSourcingTree {
List<Entity> items = InventoryUtils.getAllInventoryItems(entity);
List<String> itemIds = items.stream().map((Entity item) -> {return ItemUtils.getType(item);}).collect(Collectors.toList());
if(itemIds.contains(this.rootItemId)){
return null;
return this.itemSourceMap.get(this.rootItemId);
}
String currentRootId = this.rootItemId;
while(currentRootId != null){

View File

@ -26,6 +26,7 @@ import electrosphere.server.physics.block.editing.ServerBlockEditing;
import electrosphere.server.physics.fluid.manager.ServerFluidChunk;
import electrosphere.server.physics.terrain.editing.TerrainEditing;
import electrosphere.server.physics.terrain.manager.ServerTerrainChunk;
import electrosphere.server.player.BlockActions;
/**
* Server handling for terrain network messages
@ -88,10 +89,12 @@ public class TerrainProtocol implements ServerProtocolTemplate<TerrainMessage> {
case REQUESTEDITBLOCK: {
LoggerInterface.loggerNetworking.DEBUG("(Server) Received request to edit block at " + message.getworldX() + " " + message.getworldY() + " " + message.getworldZ());
Entity targetEntity = EntityLookupUtils.getEntityById(connectionHandler.getPlayerEntityId());
Realm playerRealm = Globals.realmManager.getEntityRealm(targetEntity);
// Realm playerRealm = Globals.realmManager.getEntityRealm(targetEntity);
Vector3i worldPos = new Vector3i(message.getworldX(),message.getworldY(),message.getworldZ());
Vector3i blockPos = new Vector3i(message.getvoxelX(),message.getvoxelY(),message.getvoxelZ());
ServerBlockEditing.editBlockArea(playerRealm, worldPos, blockPos, (short)message.getblockType(), (short)message.getblockMetadata(), message.getblockEditSize());
BlockActions.editBlock(targetEntity, worldPos, blockPos, (short)message.getblockType(), message.getblockEditSize());
// ServerBlockEditing.editBlockArea(playerRealm, worldPos, blockPos, (short)message.getblockType(), (short)message.getblockMetadata(), message.getblockEditSize());
// ServerChargeState.attemptRemoveCharges(targetEntity, 1);
} break;
case REQUESTPLACEFAB: {
Vector3i worldPos = new Vector3i(message.getworldX(),message.getworldY(),message.getworldZ());

View File

@ -30,6 +30,16 @@ public class BlackboardKeys {
*/
public static final String STRUCTURE_TARGET = "structureTarget";
/**
* The target position to place a voxel at
*/
public static final String STRUCTURE_BUILD_TARGET = "structureBuildTarget";
/**
* The block type to try to build with
*/
public static final String BUILD_BLOCK = "buildBlock";
/**
* The material currently needed for building the targeted structure
*/

View File

@ -1,8 +1,15 @@
package electrosphere.server.ai.nodes.actions.interact;
import org.joml.Vector3d;
import org.joml.Vector3i;
import electrosphere.entity.Entity;
import electrosphere.server.ai.blackboard.Blackboard;
import electrosphere.server.ai.nodes.AITreeNode;
import electrosphere.server.ai.nodes.checks.spatial.BeginStructureNode;
import electrosphere.server.ai.nodes.solvers.SolveBuildMaterialNode;
import electrosphere.server.datacell.ServerWorldData;
import electrosphere.server.player.BlockActions;
/**
* Places a block
@ -11,8 +18,17 @@ public class PlaceBlockNode implements AITreeNode {
@Override
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
// TODO Auto-generated method stub
throw new UnsupportedOperationException("Unimplemented method 'evaluate'");
Vector3d position = BeginStructureNode.getStructureBuildTarget(blackboard);
Vector3i chunkPos = ServerWorldData.convertRealToChunkSpace(position);
Vector3i blockPos = ServerWorldData.convertRealToLocalBlockSpace(position);
short blockType = BeginStructureNode.getBuildBlock(blackboard);
BlockActions.editBlock(entity, chunkPos, blockPos, blockType, 1);
SolveBuildMaterialNode.clearBuildTarget(blackboard);
return AITreeNodeResult.SUCCESS;
}
}

View File

@ -20,16 +20,49 @@ public class EquipToolbarNode implements AITreeNode {
String itemTypeKey;
/**
* Constructor
* @param itemTypeKey The blackboard key to lookup the item type under
* The block type key
*/
public EquipToolbarNode(String itemTypeKey){
this.itemTypeKey = itemTypeKey;
String blockTypeKey;
/**
* Constructor
*/
private EquipToolbarNode(){
}
/**
* Creates a EquipToolbarNode that tries to equip a type of item
* @param blockTypeKey Key that stores the item type id
* @return The EquipToolbarNode
*/
public static EquipToolbarNode equipItem(String itemTypeKey){
EquipToolbarNode rVal = new EquipToolbarNode();
rVal.itemTypeKey = itemTypeKey;
return rVal;
}
/**
* Creates a EquipToolbarNode that tries to equip a block
* @param blockTypeKey Key that stores the block type (NOT THE ENTITY TYPE)
* @return The EquipToolbarNode
*/
public static EquipToolbarNode equipBlock(String blockTypeKey){
EquipToolbarNode rVal = new EquipToolbarNode();
rVal.blockTypeKey = blockTypeKey;
return rVal;
}
@Override
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
String targetItemType = (String)blackboard.get(itemTypeKey);
String targetItemType = null;
if(this.itemTypeKey != null){
targetItemType = (String)blackboard.get(this.itemTypeKey);
} else if(this.blockTypeKey != null){
targetItemType = (String)blackboard.get(this.blockTypeKey);
} else {
throw new Error("No keys defined!");
}
//check if that item type is already equipped
ServerToolbarState serverToolbarState = ServerToolbarState.getServerToolbarState(entity);

View File

@ -9,6 +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.macro.structure.Structure;
import electrosphere.util.math.SpatialMathUtils;
/**
@ -38,9 +39,12 @@ public class FaceTargetNode implements AITreeNode {
}
if(targetRaw instanceof Vector3d){
targetPos = (Vector3d)targetRaw;
}
if(targetRaw instanceof Entity){
} else if(targetRaw instanceof Entity){
targetPos = EntityUtils.getPosition((Entity)targetRaw);
} else if(targetRaw instanceof Structure){
targetPos = ((Structure)targetRaw).getPos();
} else {
throw new Error("Unsupported target type " + targetRaw);
}
Vector3d parentPos = EntityUtils.getPosition(entity);
Quaterniond rotation = SpatialMathUtils.calculateRotationFromPointToPoint(parentPos, targetPos);

View File

@ -82,4 +82,56 @@ public class BeginStructureNode implements AITreeNode {
return (Structure)blackboard.get(BlackboardKeys.STRUCTURE_TARGET);
}
/**
* Sets the position of the voxel to target for the entity
* @param blackboard The blackboard
* @param structure The position of the voxel to target
*/
public static void setStructureBuildTarget(Blackboard blackboard, Vector3d position){
blackboard.put(BlackboardKeys.STRUCTURE_BUILD_TARGET, position);
}
/**
* Checks if the blackboard has a voxel position target
* @param blackboard The blackboard
*/
public static boolean hasStructureBuildTarget(Blackboard blackboard){
return blackboard.has(BlackboardKeys.STRUCTURE_BUILD_TARGET);
}
/**
* Gets the position of the voxel to target in the blackboard
* @param blackboard The blackboard
* @return The position of the voxel to target if it exists, null otherwise
*/
public static Vector3d getStructureBuildTarget(Blackboard blackboard){
return (Vector3d)blackboard.get(BlackboardKeys.STRUCTURE_BUILD_TARGET);
}
/**
* Sets the block type to build with
* @param blackboard The blackboard
* @param structure The block type
*/
public static void setBuildBlock(Blackboard blackboard, short position){
blackboard.put(BlackboardKeys.BUILD_BLOCK, position);
}
/**
* Checks if the blackboard has a block type to build with
* @param blackboard The blackboard
*/
public static boolean hasBuildBlock(Blackboard blackboard){
return blackboard.has(BlackboardKeys.BUILD_BLOCK);
}
/**
* Gets block type to build with
* @param blackboard The blackboard
* @return The block type to build with
*/
public static short getBuildBlock(Blackboard blackboard){
return (short)blackboard.get(BlackboardKeys.BUILD_BLOCK);
}
}

View File

@ -6,6 +6,7 @@ import electrosphere.entity.Entity;
import electrosphere.entity.EntityUtils;
import electrosphere.server.ai.blackboard.Blackboard;
import electrosphere.server.ai.nodes.AITreeNode;
import electrosphere.server.macro.structure.Structure;
/**
* Checks if the target is inside a given range of the entity
@ -41,9 +42,12 @@ public class TargetRangeCheckNode implements AITreeNode {
}
if(targetRaw instanceof Vector3d){
targetPos = (Vector3d)targetRaw;
}
if(targetRaw instanceof Entity){
} else if(targetRaw instanceof Entity){
targetPos = EntityUtils.getPosition((Entity)targetRaw);
} else if(targetRaw instanceof Structure){
targetPos = ((Structure)targetRaw).getPos();
} else {
throw new Error("Unsupported target type " + targetRaw);
}
Vector3d entPos = EntityUtils.getPosition(entity);

View File

@ -31,8 +31,8 @@ public class SolveSourcingTreeNode implements AITreeNode {
if(!blackboard.has(itemIdKey)){
return AITreeNodeResult.FAILURE;
}
if(!SolveSourcingTreeNode.hasItemSourcingTree(blackboard) || !SolveSourcingTreeNode.getItemSourcingTree(blackboard).getRootItem().equals(this.itemIdKey)){
String itemId = (String)blackboard.get(itemIdKey);
if(!SolveSourcingTreeNode.hasItemSourcingTree(blackboard) || !SolveSourcingTreeNode.getItemSourcingTree(blackboard).getRootItem().equals(itemId)){
ItemSourcingTree sourcingTree = ItemSourcingTree.create(itemId);
SolveSourcingTreeNode.setItemSourcingTree(blackboard, sourcingTree);
}

View File

@ -3,6 +3,7 @@ package electrosphere.server.ai.nodes.plan;
import java.util.Collection;
import electrosphere.entity.Entity;
import electrosphere.entity.state.life.ServerLifeTree;
import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.server.ai.blackboard.Blackboard;
import electrosphere.server.ai.blackboard.BlackboardKeys;
@ -45,6 +46,12 @@ public class TargetEntityCategoryNode implements AITreeNode {
if(!typeId.equals(goalEntityId)){
TargetEntityCategoryNode.clearTarget(blackboard);
}
if(ServerLifeTree.hasServerLifeTree(currentTarget)){
ServerLifeTree serverLifeTree = ServerLifeTree.getServerLifeTree(currentTarget);
if(!serverLifeTree.isAlive()){
TargetEntityCategoryNode.clearTarget(blackboard);
}
}
}
}
if(!TargetEntityCategoryNode.hasTarget(blackboard)){

View File

@ -1,13 +1,16 @@
package electrosphere.server.ai.nodes.solvers;
import org.joml.Vector3d;
import org.joml.Vector3i;
import electrosphere.client.block.BlockChunkData;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.game.data.block.BlockFab;
import electrosphere.game.data.block.BlockType;
import electrosphere.game.data.item.Item;
import electrosphere.server.ai.blackboard.Blackboard;
import electrosphere.server.ai.blackboard.BlackboardKeys;
import electrosphere.server.ai.nodes.AITreeNode;
import electrosphere.server.ai.nodes.checks.spatial.BeginStructureNode;
import electrosphere.server.ai.trees.struct.BuildStructureTree;
@ -37,6 +40,17 @@ public class SolveBuildMaterialNode implements AITreeNode {
BlockType blockType = Globals.gameConfigCurrent.getBlockData().getTypeFromId(blockTypeId);
String itemId = Item.getBlockTypeId(blockType);
//store the position of the block we want to place
Vector3d realPos = new Vector3d(struct.getStartPos()).add(
repairPos.x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
repairPos.y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
repairPos.z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
);
BeginStructureNode.setStructureBuildTarget(blackboard, realPos);
//set block type
BeginStructureNode.setBuildBlock(blackboard, blockTypeId);
//store
BuildStructureTree.setCurrentMaterial(blackboard, itemId);
}
@ -44,4 +58,14 @@ public class SolveBuildMaterialNode implements AITreeNode {
return AITreeNodeResult.SUCCESS;
}
/**
* Clears the build data (ie if we just finished building)
* @param blackboard The blackboard
*/
public static void clearBuildTarget(Blackboard blackboard){
blackboard.delete(BlackboardKeys.BUILD_BLOCK);
blackboard.delete(BlackboardKeys.BUILDING_MATERIAL_CURRENT);
blackboard.delete(BlackboardKeys.STRUCTURE_BUILD_TARGET);
}
}

View File

@ -31,7 +31,7 @@ public class EquipToolbarTree {
new InventoryContainsNode(BlackboardKeys.INVENTORY_CHECK_TYPE),
//try to equip the item to the toolbar
new EquipToolbarNode(BlackboardKeys.INVENTORY_CHECK_TYPE)
EquipToolbarNode.equipItem(BlackboardKeys.INVENTORY_CHECK_TYPE)
);
}

View File

@ -5,11 +5,12 @@ import electrosphere.server.ai.blackboard.Blackboard;
import electrosphere.server.ai.blackboard.BlackboardKeys;
import electrosphere.server.ai.nodes.AITreeNode;
import electrosphere.server.ai.nodes.actions.interact.PlaceBlockNode;
import electrosphere.server.ai.nodes.actions.inventory.EquipToolbarNode;
import electrosphere.server.ai.nodes.checks.inventory.InventoryContainsNode;
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
import electrosphere.server.ai.nodes.meta.collections.SequenceNode;
import electrosphere.server.ai.nodes.meta.debug.PublishStatusNode;
import electrosphere.server.ai.nodes.meta.decorators.RunnerNode;
import electrosphere.server.ai.nodes.meta.decorators.SucceederNode;
import electrosphere.server.ai.nodes.solvers.SolveBuildMaterialNode;
import electrosphere.server.ai.trees.creature.AcquireItemTree;
import electrosphere.server.ai.trees.creature.MoveToTarget;
@ -41,14 +42,13 @@ public class BuildStructureTree {
new SequenceNode(
new InventoryContainsNode(BlackboardKeys.BUILDING_MATERIAL_CURRENT),
//if we're within range to place the material
new SelectorNode(
//in range, place block
new PlaceBlockNode(),
//not in range, move to within range
new SequenceNode(
//TODO: Solve for where to move towards
MoveToTarget.create(CollisionEngine.DEFAULT_INTERACT_DISTANCE, BlackboardKeys.ENTITY_TARGET)
)
//not in range, move to within range
MoveToTarget.create(CollisionEngine.DEFAULT_INTERACT_DISTANCE, BlackboardKeys.STRUCTURE_TARGET),
//equip the type of block to place
EquipToolbarNode.equipBlock(BlackboardKeys.BUILDING_MATERIAL_CURRENT),
//in range, place block
new PlaceBlockNode()
)
)
),
@ -56,9 +56,9 @@ public class BuildStructureTree {
new SequenceNode(
new PublishStatusNode("Acquire building material"),
//try to find building materials
AcquireItemTree.create(BlackboardKeys.BUILDING_MATERIAL_CURRENT),
new RunnerNode(null)
)
AcquireItemTree.create(BlackboardKeys.BUILDING_MATERIAL_CURRENT)
),
new SucceederNode(null)
)
);
}

View File

@ -18,7 +18,7 @@ public class StructurePlacementUtils {
* @return The position
*/
public static Vector3d getPlacementPosition(MacroData macroData, StructureData structureData, Vector3d approxLocation){
return approxLocation;
return new Vector3d(approxLocation);
}
}

View File

@ -33,7 +33,11 @@ public class StructureRepairUtils {
for(int x = 0; x < fab.getDimensions().x; x++){
for(int y = 0; y < fab.getDimensions().y; y++){
for(int z = 0; z < fab.getDimensions().z; z++){
Vector3d offsetPos = new Vector3d(structStartPos).add(x,y,z);
Vector3d offsetPos = new Vector3d(structStartPos).add(
x * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
y * BlockChunkData.BLOCK_SIZE_MULTIPLIER,
z * BlockChunkData.BLOCK_SIZE_MULTIPLIER
);
Vector3i chunkPos = ServerWorldData.convertRealToChunkSpace(offsetPos);
Vector3i blockPos = ServerWorldData.convertRealToLocalBlockSpace(offsetPos);
BlockChunkData blockChunkData = griddedDataCellManager.getBlocksAtPosition(chunkPos);
@ -46,4 +50,37 @@ public class StructureRepairUtils {
return null;
}
/**
* Solves for whether the structure can be repaired or not
* @param realm The realm the structure is within
* @param struct The structure
*/
public static void updateRepairableStatus(Realm realm, Structure struct){
//error checking
if(!(realm.getDataCellManager() instanceof GriddedDataCellManager)){
throw new Error("Realm is not a gridded realm!");
}
//assume it's not repairable, then check if this is true
struct.setRepairable(false);
BlockFab fab = struct.getFab();
Vector3d structStartPos = struct.getStartPos();
GriddedDataCellManager griddedDataCellManager = (GriddedDataCellManager)realm.getDataCellManager();
for(int x = 0; x < fab.getDimensions().x; x++){
for(int y = 0; y < fab.getDimensions().y; y++){
for(int z = 0; z < fab.getDimensions().z; z++){
Vector3d offsetPos = new Vector3d(structStartPos).add(x,y,z);
Vector3i chunkPos = ServerWorldData.convertRealToChunkSpace(offsetPos);
Vector3i blockPos = ServerWorldData.convertRealToLocalBlockSpace(offsetPos);
BlockChunkData blockChunkData = griddedDataCellManager.getBlocksAtPosition(chunkPos);
if(blockChunkData.getType(blockPos.x, blockPos.y, blockPos.z) != fab.getType(x, y, z)){
struct.setRepairable(true);
return;
}
}
}
}
}
}

View File

@ -0,0 +1,46 @@
package electrosphere.server.player;
import org.joml.Vector3i;
import electrosphere.engine.Globals;
import electrosphere.entity.Entity;
import electrosphere.entity.state.equip.ServerToolbarState;
import electrosphere.entity.state.item.ServerChargeState;
import electrosphere.entity.types.common.CommonEntityUtils;
import electrosphere.game.data.block.BlockType;
import electrosphere.game.data.item.Item;
import electrosphere.server.datacell.Realm;
import electrosphere.server.physics.block.editing.ServerBlockEditing;
/**
* Actions involving blocks
*/
public class BlockActions {
/**
* Tries to edit a block
* @param creature The creature that is performing the edit
* @param chunkPos The chunk position
* @param blockPos The block position
* @param blockType The type of block to edit to
* @param editSize The size of the edit
*/
public static void editBlock(Entity creature, Vector3i chunkPos, Vector3i blockPos, short blockType, int editSize){
Realm playerRealm = Globals.realmManager.getEntityRealm(creature);
if(ServerToolbarState.hasServerToolbarState(creature)){
//check that we have the block equipped
ServerToolbarState serverToolbarState = ServerToolbarState.getServerToolbarState(creature);
Entity equippedItem = serverToolbarState.getRealWorldItem();
String equippedItemType = CommonEntityUtils.getEntitySubtype(equippedItem);
BlockType blockTypeData = Globals.gameConfigCurrent.getBlockData().getTypeFromId((int)blockType);
String goalBlockEntityId = Item.getBlockTypeId(blockTypeData);
if(equippedItemType.equals(goalBlockEntityId)){
//place the block
ServerBlockEditing.editBlockArea(playerRealm, chunkPos, blockPos, blockType, (short)0, editSize);
ServerChargeState.attemptRemoveCharges(creature, 1);
}
}
}
}