diff --git a/assets/Data/game/recipes/voxelrecipes.json b/assets/Data/game/recipes/voxelrecipes.json index 04942375..14dd0550 100644 --- a/assets/Data/game/recipes/voxelrecipes.json +++ b/assets/Data/game/recipes/voxelrecipes.json @@ -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": [ diff --git a/docs/src/progress/renderertodo.md b/docs/src/progress/renderertodo.md index 4685afca..b9e08674 100644 --- a/docs/src/progress/renderertodo.md +++ b/docs/src/progress/renderertodo.md @@ -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 + diff --git a/src/main/java/electrosphere/game/data/item/source/ItemSourcingTree.java b/src/main/java/electrosphere/game/data/item/source/ItemSourcingTree.java index bd4d50c6..6ef580cb 100644 --- a/src/main/java/electrosphere/game/data/item/source/ItemSourcingTree.java +++ b/src/main/java/electrosphere/game/data/item/source/ItemSourcingTree.java @@ -78,7 +78,7 @@ public class ItemSourcingTree { List items = InventoryUtils.getAllInventoryItems(entity); List 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){ diff --git a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java index bb1be4db..161666d8 100644 --- a/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java +++ b/src/main/java/electrosphere/net/server/protocol/TerrainProtocol.java @@ -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 { 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()); diff --git a/src/main/java/electrosphere/server/ai/blackboard/BlackboardKeys.java b/src/main/java/electrosphere/server/ai/blackboard/BlackboardKeys.java index 911abe6d..c5395e98 100644 --- a/src/main/java/electrosphere/server/ai/blackboard/BlackboardKeys.java +++ b/src/main/java/electrosphere/server/ai/blackboard/BlackboardKeys.java @@ -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 */ diff --git a/src/main/java/electrosphere/server/ai/nodes/actions/interact/PlaceBlockNode.java b/src/main/java/electrosphere/server/ai/nodes/actions/interact/PlaceBlockNode.java index 2a0510db..a557c5aa 100644 --- a/src/main/java/electrosphere/server/ai/nodes/actions/interact/PlaceBlockNode.java +++ b/src/main/java/electrosphere/server/ai/nodes/actions/interact/PlaceBlockNode.java @@ -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; } } diff --git a/src/main/java/electrosphere/server/ai/nodes/actions/inventory/EquipToolbarNode.java b/src/main/java/electrosphere/server/ai/nodes/actions/inventory/EquipToolbarNode.java index a561f02b..81d513cd 100644 --- a/src/main/java/electrosphere/server/ai/nodes/actions/inventory/EquipToolbarNode.java +++ b/src/main/java/electrosphere/server/ai/nodes/actions/inventory/EquipToolbarNode.java @@ -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); diff --git a/src/main/java/electrosphere/server/ai/nodes/actions/move/FaceTargetNode.java b/src/main/java/electrosphere/server/ai/nodes/actions/move/FaceTargetNode.java index f2b17be1..57603678 100644 --- a/src/main/java/electrosphere/server/ai/nodes/actions/move/FaceTargetNode.java +++ b/src/main/java/electrosphere/server/ai/nodes/actions/move/FaceTargetNode.java @@ -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); diff --git a/src/main/java/electrosphere/server/ai/nodes/checks/spatial/BeginStructureNode.java b/src/main/java/electrosphere/server/ai/nodes/checks/spatial/BeginStructureNode.java index e74f57db..af79d4d3 100644 --- a/src/main/java/electrosphere/server/ai/nodes/checks/spatial/BeginStructureNode.java +++ b/src/main/java/electrosphere/server/ai/nodes/checks/spatial/BeginStructureNode.java @@ -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); + } + } diff --git a/src/main/java/electrosphere/server/ai/nodes/checks/spatial/TargetRangeCheckNode.java b/src/main/java/electrosphere/server/ai/nodes/checks/spatial/TargetRangeCheckNode.java index c0eb520e..553f6850 100644 --- a/src/main/java/electrosphere/server/ai/nodes/checks/spatial/TargetRangeCheckNode.java +++ b/src/main/java/electrosphere/server/ai/nodes/checks/spatial/TargetRangeCheckNode.java @@ -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); diff --git a/src/main/java/electrosphere/server/ai/nodes/plan/SolveSourcingTreeNode.java b/src/main/java/electrosphere/server/ai/nodes/plan/SolveSourcingTreeNode.java index 61b58b7f..3a4237b3 100644 --- a/src/main/java/electrosphere/server/ai/nodes/plan/SolveSourcingTreeNode.java +++ b/src/main/java/electrosphere/server/ai/nodes/plan/SolveSourcingTreeNode.java @@ -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); + 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); } diff --git a/src/main/java/electrosphere/server/ai/nodes/plan/TargetEntityCategoryNode.java b/src/main/java/electrosphere/server/ai/nodes/plan/TargetEntityCategoryNode.java index bac694ca..2de6d678 100644 --- a/src/main/java/electrosphere/server/ai/nodes/plan/TargetEntityCategoryNode.java +++ b/src/main/java/electrosphere/server/ai/nodes/plan/TargetEntityCategoryNode.java @@ -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)){ diff --git a/src/main/java/electrosphere/server/ai/nodes/solvers/SolveBuildMaterialNode.java b/src/main/java/electrosphere/server/ai/nodes/solvers/SolveBuildMaterialNode.java index b45e1e1e..ac344832 100644 --- a/src/main/java/electrosphere/server/ai/nodes/solvers/SolveBuildMaterialNode.java +++ b/src/main/java/electrosphere/server/ai/nodes/solvers/SolveBuildMaterialNode.java @@ -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,11 +40,32 @@ 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); } 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); + } } diff --git a/src/main/java/electrosphere/server/ai/trees/creature/inventory/EquipToolbarTree.java b/src/main/java/electrosphere/server/ai/trees/creature/inventory/EquipToolbarTree.java index cdf59de1..637c4717 100644 --- a/src/main/java/electrosphere/server/ai/trees/creature/inventory/EquipToolbarTree.java +++ b/src/main/java/electrosphere/server/ai/trees/creature/inventory/EquipToolbarTree.java @@ -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) ); } diff --git a/src/main/java/electrosphere/server/ai/trees/struct/BuildStructureTree.java b/src/main/java/electrosphere/server/ai/trees/struct/BuildStructureTree.java index 020d3744..f6a0cdfa 100644 --- a/src/main/java/electrosphere/server/ai/trees/struct/BuildStructureTree.java +++ b/src/main/java/electrosphere/server/ai/trees/struct/BuildStructureTree.java @@ -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(), + new SequenceNode( //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) - ) + 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) ) ); } diff --git a/src/main/java/electrosphere/server/macro/utils/StructurePlacementUtils.java b/src/main/java/electrosphere/server/macro/utils/StructurePlacementUtils.java index 1d98d244..b807b8ad 100644 --- a/src/main/java/electrosphere/server/macro/utils/StructurePlacementUtils.java +++ b/src/main/java/electrosphere/server/macro/utils/StructurePlacementUtils.java @@ -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); } } diff --git a/src/main/java/electrosphere/server/macro/utils/StructureRepairUtils.java b/src/main/java/electrosphere/server/macro/utils/StructureRepairUtils.java index 50cad024..38959cd7 100644 --- a/src/main/java/electrosphere/server/macro/utils/StructureRepairUtils.java +++ b/src/main/java/electrosphere/server/macro/utils/StructureRepairUtils.java @@ -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; + } + } + } + } + } + } diff --git a/src/main/java/electrosphere/server/player/BlockActions.java b/src/main/java/electrosphere/server/player/BlockActions.java new file mode 100644 index 00000000..ebfc8de0 --- /dev/null +++ b/src/main/java/electrosphere/server/player/BlockActions.java @@ -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); + } + } + } + +}