This commit is contained in:
parent
48622bb08f
commit
f0ff713413
@ -1634,6 +1634,8 @@ AI work
|
|||||||
Many new AI trees
|
Many new AI trees
|
||||||
- AI can seek out items
|
- AI can seek out items
|
||||||
- AI can harvest entities
|
- AI can harvest entities
|
||||||
|
- AI can pick up items
|
||||||
|
- AI can craft
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -735,12 +735,12 @@ public class InventoryUtils {
|
|||||||
rVal.addAll(equipInventory.getItems());
|
rVal.addAll(equipInventory.getItems());
|
||||||
}
|
}
|
||||||
if(InventoryUtils.hasNaturalInventory(creature)){
|
if(InventoryUtils.hasNaturalInventory(creature)){
|
||||||
UnrelationalInventoryState equipInventory = InventoryUtils.getNaturalInventory(creature);
|
UnrelationalInventoryState naturalInventory = InventoryUtils.getNaturalInventory(creature);
|
||||||
rVal.addAll(equipInventory.getItems());
|
rVal.addAll(naturalInventory.getItems());
|
||||||
}
|
}
|
||||||
if(InventoryUtils.hasToolbarInventory(creature)){
|
if(InventoryUtils.hasToolbarInventory(creature)){
|
||||||
RelationalInventoryState equipInventory = InventoryUtils.getToolbarInventory(creature);
|
RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(creature);
|
||||||
rVal.addAll(equipInventory.getItems());
|
rVal.addAll(toolbarInventory.getItems());
|
||||||
}
|
}
|
||||||
//filter null items
|
//filter null items
|
||||||
rVal = rVal.stream().filter((Entity el) -> {return el != null;}).collect(Collectors.toList());
|
rVal = rVal.stream().filter((Entity el) -> {return el != null;}).collect(Collectors.toList());
|
||||||
|
|||||||
@ -27,8 +27,17 @@ public class ItemSourcingData {
|
|||||||
* Fell a tree
|
* Fell a tree
|
||||||
*/
|
*/
|
||||||
TREE,
|
TREE,
|
||||||
|
/**
|
||||||
|
* Pick up the item off the floor
|
||||||
|
*/
|
||||||
|
PICKUP,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The goal item type
|
||||||
|
*/
|
||||||
|
String goalItem;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of recipes that create this item
|
* The list of recipes that create this item
|
||||||
*/
|
*/
|
||||||
@ -46,11 +55,13 @@ public class ItemSourcingData {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
* @param goalItem The item that this object stores sources of (ie if this is rocks, all the source lists should contain ways to get rocks)
|
||||||
* @param recipes The recipes to source from
|
* @param recipes The recipes to source from
|
||||||
* @param harvestTargets The objects to harvest from
|
* @param harvestTargets The objects to harvest from
|
||||||
* @param trees The trees to drop from
|
* @param trees The trees to drop from
|
||||||
*/
|
*/
|
||||||
public ItemSourcingData(List<RecipeData> recipes, List<CommonEntityType> harvestTargets, List<FoliageType> trees){
|
public ItemSourcingData(String goalItem, List<RecipeData> recipes, List<CommonEntityType> harvestTargets, List<FoliageType> trees){
|
||||||
|
this.goalItem = goalItem;
|
||||||
this.recipes = recipes;
|
this.recipes = recipes;
|
||||||
this.harvestTargets = harvestTargets;
|
this.harvestTargets = harvestTargets;
|
||||||
this.trees = trees;
|
this.trees = trees;
|
||||||
@ -80,6 +91,14 @@ public class ItemSourcingData {
|
|||||||
return trees;
|
return trees;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the item that this object stores sources of (ie if this is rocks, all the source lists should contain ways to get rocks)
|
||||||
|
* @return The item type id
|
||||||
|
*/
|
||||||
|
public String getGoalItem(){
|
||||||
|
return goalItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -100,7 +100,7 @@ public class ItemSourcingMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//store the sourcing data
|
//store the sourcing data
|
||||||
ItemSourcingData sourcingData = new ItemSourcingData(recipes, harvestTargets, trees);
|
ItemSourcingData sourcingData = new ItemSourcingData(item.getId(), recipes, harvestTargets, trees);
|
||||||
sourcingMap.itemSourcingDataMap.put(item.getId(),sourcingData);
|
sourcingMap.itemSourcingDataMap.put(item.getId(),sourcingData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,27 +1,15 @@
|
|||||||
package electrosphere.net.server.protocol;
|
package electrosphere.net.server.protocol;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import electrosphere.engine.Globals;
|
import electrosphere.engine.Globals;
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
import electrosphere.entity.state.inventory.InventoryUtils;
|
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||||
import electrosphere.entity.state.inventory.RelationalInventoryState;
|
|
||||||
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
|
|
||||||
import electrosphere.entity.state.item.ServerChargeState;
|
|
||||||
import electrosphere.game.data.crafting.RecipeData;
|
import electrosphere.game.data.crafting.RecipeData;
|
||||||
import electrosphere.game.data.crafting.RecipeIngredientData;
|
|
||||||
import electrosphere.game.data.item.Item;
|
|
||||||
import electrosphere.game.data.item.ItemDataMap;
|
|
||||||
import electrosphere.logger.LoggerInterface;
|
import electrosphere.logger.LoggerInterface;
|
||||||
import electrosphere.net.parser.net.message.InventoryMessage;
|
import electrosphere.net.parser.net.message.InventoryMessage;
|
||||||
import electrosphere.net.server.ServerConnectionHandler;
|
import electrosphere.net.server.ServerConnectionHandler;
|
||||||
import electrosphere.net.template.ServerProtocolTemplate;
|
import electrosphere.net.template.ServerProtocolTemplate;
|
||||||
import electrosphere.server.datacell.ServerDataCell;
|
|
||||||
import electrosphere.server.datacell.utils.DataCellSearchUtils;
|
|
||||||
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
import electrosphere.server.datacell.utils.EntityLookupUtils;
|
||||||
|
import electrosphere.server.player.CraftingActions;
|
||||||
import electrosphere.server.player.PlayerActions;
|
import electrosphere.server.player.PlayerActions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -108,7 +96,7 @@ public class InventoryProtocol implements ServerProtocolTemplate<InventoryMessag
|
|||||||
Entity workshopEntity = EntityLookupUtils.getEntityById(message.getstationId());
|
Entity workshopEntity = EntityLookupUtils.getEntityById(message.getstationId());
|
||||||
RecipeData recipe = Globals.gameConfigCurrent.getRecipeMap().getType(message.getrecipeId());
|
RecipeData recipe = Globals.gameConfigCurrent.getRecipeMap().getType(message.getrecipeId());
|
||||||
if(target != null && recipe != null){
|
if(target != null && recipe != null){
|
||||||
this.attemptCraft(target,workshopEntity,recipe);
|
CraftingActions.attemptCraft(target,workshopEntity,recipe);
|
||||||
// System.out.println(message.getentityId() + " " + message.getstationId() + " " + message.getrecipeId());
|
// System.out.println(message.getentityId() + " " + message.getstationId() + " " + message.getrecipeId());
|
||||||
// InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
|
// InventoryUtils.serverGetInventoryState(target).addNetworkMessage(message);
|
||||||
}
|
}
|
||||||
@ -122,148 +110,4 @@ public class InventoryProtocol implements ServerProtocolTemplate<InventoryMessag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Attempts to craft an item
|
|
||||||
* @param crafter The entity performing the crafting
|
|
||||||
* @param station The (optional) station for crafting
|
|
||||||
* @param recipe The recipe to craft
|
|
||||||
*/
|
|
||||||
private void attemptCraft(Entity crafter, Entity station, RecipeData recipe){
|
|
||||||
if(InventoryUtils.serverGetInventoryState(crafter) == null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
UnrelationalInventoryState naturalInventory = InventoryUtils.getNaturalInventory(crafter);
|
|
||||||
RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(crafter);
|
|
||||||
|
|
||||||
//get data obj
|
|
||||||
ItemDataMap itemMap = Globals.gameConfigCurrent.getItemMap();
|
|
||||||
|
|
||||||
//get reagents
|
|
||||||
List<Entity> reagentList = new LinkedList<Entity>();
|
|
||||||
boolean hasReagents = true;
|
|
||||||
Map<String,Integer> ingredientTargetMap = new HashMap<String,Integer>();
|
|
||||||
Map<String,Integer> ingredientAccretionMap = new HashMap<String,Integer>();
|
|
||||||
//find the reagents we're going to use to craft
|
|
||||||
for(RecipeIngredientData ingredient : recipe.getIngredients()){
|
|
||||||
ingredientTargetMap.put(ingredient.getItemType(),ingredient.getCount());
|
|
||||||
ingredientAccretionMap.put(ingredient.getItemType(),0);
|
|
||||||
int found = 0;
|
|
||||||
if(naturalInventory != null){
|
|
||||||
for(Entity itemEnt : naturalInventory.getItems()){
|
|
||||||
if(itemMap.getItem(itemEnt).getId().matches(ingredient.getItemType())){
|
|
||||||
if(ServerChargeState.hasServerChargeState(itemEnt)){
|
|
||||||
ServerChargeState serverChargeState = ServerChargeState.getServerChargeState(itemEnt);
|
|
||||||
found = found + serverChargeState.getCharges();
|
|
||||||
} else {
|
|
||||||
found++;
|
|
||||||
}
|
|
||||||
reagentList.add(itemEnt);
|
|
||||||
}
|
|
||||||
if(found >= ingredient.getCount()){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(toolbarInventory != null){
|
|
||||||
for(Entity itemEnt : toolbarInventory.getItems()){
|
|
||||||
if(itemEnt == null){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(itemMap.getItem(itemEnt).getId().matches(ingredient.getItemType())){
|
|
||||||
if(ServerChargeState.hasServerChargeState(itemEnt)){
|
|
||||||
ServerChargeState serverChargeState = ServerChargeState.getServerChargeState(itemEnt);
|
|
||||||
found = found + serverChargeState.getCharges();
|
|
||||||
} else {
|
|
||||||
found++;
|
|
||||||
}
|
|
||||||
reagentList.add(itemEnt);
|
|
||||||
}
|
|
||||||
if(found >= ingredient.getCount()){
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(found < ingredient.getCount()){
|
|
||||||
hasReagents = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(hasReagents){
|
|
||||||
for(Entity reagentEnt : reagentList){
|
|
||||||
|
|
||||||
//determine how many we need to still remove
|
|
||||||
Item itemData = itemMap.getItem(reagentEnt);
|
|
||||||
int targetToRemove = ingredientTargetMap.get(itemData.getId());
|
|
||||||
int alreadyFound = ingredientAccretionMap.get(itemData.getId());
|
|
||||||
if(alreadyFound > targetToRemove){
|
|
||||||
throw new Error("Removed too many ingredients! " + targetToRemove + " " + alreadyFound);
|
|
||||||
} else if(alreadyFound == targetToRemove){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if(ServerChargeState.hasServerChargeState(reagentEnt)){
|
|
||||||
ServerChargeState serverChargeState = ServerChargeState.getServerChargeState(reagentEnt);
|
|
||||||
int available = serverChargeState.getCharges();
|
|
||||||
|
|
||||||
if(available > targetToRemove - alreadyFound){
|
|
||||||
int chargesToRemove = targetToRemove - alreadyFound;
|
|
||||||
serverChargeState.attemptAddCharges(-chargesToRemove);
|
|
||||||
//just remove charges
|
|
||||||
ingredientAccretionMap.put(itemData.getId(),alreadyFound + chargesToRemove);
|
|
||||||
} else {
|
|
||||||
//remove item entirely (consuming all charges)
|
|
||||||
if(naturalInventory != null){
|
|
||||||
naturalInventory.removeItem(reagentEnt);
|
|
||||||
}
|
|
||||||
if(toolbarInventory != null){
|
|
||||||
toolbarInventory.tryRemoveItem(reagentEnt);
|
|
||||||
}
|
|
||||||
this.deleteItemInInventory(crafter, reagentEnt);
|
|
||||||
ingredientAccretionMap.put(itemData.getId(),alreadyFound + available);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(naturalInventory != null){
|
|
||||||
naturalInventory.removeItem(reagentEnt);
|
|
||||||
}
|
|
||||||
if(toolbarInventory != null){
|
|
||||||
toolbarInventory.tryRemoveItem(reagentEnt);
|
|
||||||
}
|
|
||||||
this.deleteItemInInventory(crafter, reagentEnt);
|
|
||||||
ingredientAccretionMap.put(itemData.getId(),alreadyFound + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(RecipeIngredientData product : recipe.getProducts()){
|
|
||||||
Item productType = itemMap.getItem(product.getItemType());
|
|
||||||
if(productType == null){
|
|
||||||
throw new Error("Could not locate product definition! " + productType + " " + product.getItemType());
|
|
||||||
}
|
|
||||||
InventoryUtils.serverCreateInventoryItem(crafter, product.getItemType(), product.getCount());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete an item that is in an inventory
|
|
||||||
* @param parent The parent entity that contains the in-inventory item
|
|
||||||
* @param itemEnt The item that is in an inventory
|
|
||||||
*/
|
|
||||||
private void deleteItemInInventory(Entity parent, Entity inInventory){
|
|
||||||
//the parent entity's data cell
|
|
||||||
ServerDataCell dataCell = DataCellSearchUtils.getEntityDataCell(parent);
|
|
||||||
//broadcast destroy entity
|
|
||||||
dataCell.broadcastNetworkMessage(InventoryMessage.constructremoveItemFromInventoryMessage(inInventory.getId()));
|
|
||||||
//remove the inventories
|
|
||||||
UnrelationalInventoryState naturalInventory = InventoryUtils.getNaturalInventory(parent);
|
|
||||||
RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(parent);
|
|
||||||
if(naturalInventory != null){
|
|
||||||
naturalInventory.removeItem(inInventory);
|
|
||||||
}
|
|
||||||
if(toolbarInventory != null){
|
|
||||||
toolbarInventory.tryRemoveItem(inInventory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,6 +50,11 @@ public class BlackboardKeys {
|
|||||||
*/
|
*/
|
||||||
public static final String ITEM_SOURCING_DATA = "itemSourcingData";
|
public static final String ITEM_SOURCING_DATA = "itemSourcingData";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The category of item to target
|
||||||
|
*/
|
||||||
|
public static final String ITEM_TARGET_CATEGORY = "itemTargetCategory";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of entity to try to harvest
|
* The type of entity to try to harvest
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -0,0 +1,28 @@
|
|||||||
|
package electrosphere.server.ai.nodes.actions.interact;
|
||||||
|
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.game.data.crafting.RecipeData;
|
||||||
|
import electrosphere.game.data.item.source.ItemSourcingData;
|
||||||
|
import electrosphere.server.ai.blackboard.Blackboard;
|
||||||
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
|
import electrosphere.server.ai.nodes.plan.SolveSourcingTreeNode;
|
||||||
|
import electrosphere.server.player.CraftingActions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to craft an item
|
||||||
|
*/
|
||||||
|
public class CraftNode implements AITreeNode {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AITreeNodeResult evaluate(Entity entity, Blackboard blackboard) {
|
||||||
|
ItemSourcingData sourcingData = SolveSourcingTreeNode.getItemSourcingData(blackboard);
|
||||||
|
for(RecipeData recipe : sourcingData.getRecipes()){
|
||||||
|
if(CraftingActions.canCraft(entity, null, recipe)){
|
||||||
|
CraftingActions.attemptCraft(entity, null, recipe);
|
||||||
|
return AITreeNodeResult.SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return AITreeNodeResult.FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,11 +1,17 @@
|
|||||||
package electrosphere.server.ai.nodes.checks.inventory;
|
package electrosphere.server.ai.nodes.checks.inventory;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import electrosphere.entity.Entity;
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.types.common.CommonEntityUtils;
|
||||||
import electrosphere.game.data.item.source.ItemSourcingData;
|
import electrosphere.game.data.item.source.ItemSourcingData;
|
||||||
import electrosphere.game.data.item.source.ItemSourcingData.SourcingType;
|
import electrosphere.game.data.item.source.ItemSourcingData.SourcingType;
|
||||||
import electrosphere.server.ai.blackboard.Blackboard;
|
import electrosphere.server.ai.blackboard.Blackboard;
|
||||||
import electrosphere.server.ai.nodes.AITreeNode;
|
import electrosphere.server.ai.nodes.AITreeNode;
|
||||||
import electrosphere.server.ai.nodes.plan.SolveSourcingTreeNode;
|
import electrosphere.server.ai.nodes.plan.SolveSourcingTreeNode;
|
||||||
|
import electrosphere.server.ai.services.NearbyEntityService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the supplied type of sourcing is the path for the current target item to acquire
|
* Checks if the supplied type of sourcing is the path for the current target item to acquire
|
||||||
@ -17,12 +23,19 @@ public class SourcingTypeNode implements AITreeNode {
|
|||||||
*/
|
*/
|
||||||
SourcingType sourcingType;
|
SourcingType sourcingType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The blackboard key storing the target entity type id
|
||||||
|
*/
|
||||||
|
String targetTypeKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
* @param targetTypeKey The blackboard key storing the target entity type id
|
||||||
* @param sourcingType The type of sourcing to check
|
* @param sourcingType The type of sourcing to check
|
||||||
*/
|
*/
|
||||||
public SourcingTypeNode(SourcingType sourcingType){
|
public SourcingTypeNode(SourcingType sourcingType, String targetTypeKey){
|
||||||
this.sourcingType = sourcingType;
|
this.sourcingType = sourcingType;
|
||||||
|
this.targetTypeKey = targetTypeKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -38,6 +51,15 @@ public class SourcingTypeNode implements AITreeNode {
|
|||||||
|
|
||||||
//succeed based on the type of sourcing that this node is set for
|
//succeed based on the type of sourcing that this node is set for
|
||||||
switch(this.sourcingType){
|
switch(this.sourcingType){
|
||||||
|
case PICKUP: {
|
||||||
|
//see if the entity is in the vicinity
|
||||||
|
String targetEntityType = (String)blackboard.get(this.targetTypeKey);
|
||||||
|
Collection<Entity> nearbyEntities = NearbyEntityService.getNearbyEntities(blackboard);
|
||||||
|
List<String> types = nearbyEntities.stream().map((Entity ent) -> {return CommonEntityUtils.getEntitySubtype(ent);}).collect(Collectors.toList());
|
||||||
|
if(types.contains(targetEntityType)){
|
||||||
|
return AITreeNodeResult.SUCCESS;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case RECIPE: {
|
case RECIPE: {
|
||||||
if(sourcingData.getRecipes().size() > 0){
|
if(sourcingData.getRecipes().size() > 0){
|
||||||
return AITreeNodeResult.SUCCESS;
|
return AITreeNodeResult.SUCCESS;
|
||||||
|
|||||||
@ -46,6 +46,7 @@ public class SolveSourcingTreeNode implements AITreeNode {
|
|||||||
HarvestNode.setHarvestTargetType(blackboard, sourcingData.getHarvestTargets().get(0).getId());
|
HarvestNode.setHarvestTargetType(blackboard, sourcingData.getHarvestTargets().get(0).getId());
|
||||||
}
|
}
|
||||||
SolveSourcingTreeNode.setItemSourcingData(blackboard, sourcingData);
|
SolveSourcingTreeNode.setItemSourcingData(blackboard, sourcingData);
|
||||||
|
SolveSourcingTreeNode.setItemTargetCategory(blackboard, sourcingData.getGoalItem());
|
||||||
return AITreeNodeResult.SUCCESS;
|
return AITreeNodeResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,4 +104,31 @@ public class SolveSourcingTreeNode implements AITreeNode {
|
|||||||
return (ItemSourcingData)blackboard.get(BlackboardKeys.ITEM_SOURCING_DATA);
|
return (ItemSourcingData)blackboard.get(BlackboardKeys.ITEM_SOURCING_DATA);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the item target category of the blackboard
|
||||||
|
* @param blackboard The blackboard
|
||||||
|
* @param tree The data
|
||||||
|
*/
|
||||||
|
public static void setItemTargetCategory(Blackboard blackboard, String data){
|
||||||
|
blackboard.put(BlackboardKeys.ITEM_TARGET_CATEGORY, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the blackboard has an item target category
|
||||||
|
* @param blackboard The blackboard
|
||||||
|
* @return The item sourcing data
|
||||||
|
*/
|
||||||
|
public static boolean hasItemTargetCategory(Blackboard blackboard){
|
||||||
|
return blackboard.has(BlackboardKeys.ITEM_TARGET_CATEGORY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the item target category of the blackboard
|
||||||
|
* @param blackboard The blackboard
|
||||||
|
* @return The item target category
|
||||||
|
*/
|
||||||
|
public static String getItemTargetCategory(Blackboard blackboard){
|
||||||
|
return (String)blackboard.get(BlackboardKeys.ITEM_TARGET_CATEGORY);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import electrosphere.collision.CollisionEngine;
|
|||||||
import electrosphere.game.data.item.source.ItemSourcingData.SourcingType;
|
import electrosphere.game.data.item.source.ItemSourcingData.SourcingType;
|
||||||
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.interact.CollectItemNode;
|
||||||
|
import electrosphere.server.ai.nodes.actions.interact.CraftNode;
|
||||||
import electrosphere.server.ai.nodes.actions.interact.HarvestNode;
|
import electrosphere.server.ai.nodes.actions.interact.HarvestNode;
|
||||||
import electrosphere.server.ai.nodes.checks.inventory.SourcingTypeNode;
|
import electrosphere.server.ai.nodes.checks.inventory.SourcingTypeNode;
|
||||||
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
|
import electrosphere.server.ai.nodes.meta.collections.SelectorNode;
|
||||||
@ -35,17 +37,27 @@ public class AcquireItemTree {
|
|||||||
//solve how we're going to get this top level item
|
//solve how we're going to get this top level item
|
||||||
new SolveSourcingTreeNode(blackboardKey),
|
new SolveSourcingTreeNode(blackboardKey),
|
||||||
new SelectorNode(
|
new SelectorNode(
|
||||||
|
new SequenceNode(
|
||||||
|
new PublishStatusNode("Pick up an item"),
|
||||||
|
//check if we should be sourcing this item by picking it up
|
||||||
|
new SourcingTypeNode(SourcingType.PICKUP, BlackboardKeys.ITEM_TARGET_CATEGORY),
|
||||||
|
//logic to pick up the item
|
||||||
|
new TargetEntityCategoryNode(BlackboardKeys.ITEM_TARGET_CATEGORY),
|
||||||
|
MoveToTarget.create(CollisionEngine.DEFAULT_INTERACT_DISTANCE, BlackboardKeys.ENTITY_TARGET),
|
||||||
|
new CollectItemNode(),
|
||||||
|
new RunnerNode(null)
|
||||||
|
),
|
||||||
new SequenceNode(
|
new SequenceNode(
|
||||||
new PublishStatusNode("Craft an item"),
|
new PublishStatusNode("Craft an item"),
|
||||||
//check if we should be sourcing this from a recipe
|
//check if we should be sourcing this from a recipe
|
||||||
new SourcingTypeNode(SourcingType.RECIPE),
|
new SourcingTypeNode(SourcingType.RECIPE, blackboardKey),
|
||||||
//TODO: logic to craft a recipe
|
new CraftNode(),
|
||||||
new RunnerNode(null)
|
new RunnerNode(null)
|
||||||
),
|
),
|
||||||
new SequenceNode(
|
new SequenceNode(
|
||||||
new PublishStatusNode("Harvest an item"),
|
new PublishStatusNode("Harvest an item"),
|
||||||
//check if we should be sourcing this from harvesting foliage
|
//check if we should be sourcing this from harvesting foliage
|
||||||
new SourcingTypeNode(SourcingType.HARVEST),
|
new SourcingTypeNode(SourcingType.HARVEST, blackboardKey),
|
||||||
new TargetEntityCategoryNode(BlackboardKeys.HARVEST_TARGET_TYPE),
|
new TargetEntityCategoryNode(BlackboardKeys.HARVEST_TARGET_TYPE),
|
||||||
MoveToTarget.create(CollisionEngine.DEFAULT_INTERACT_DISTANCE, BlackboardKeys.ENTITY_TARGET),
|
MoveToTarget.create(CollisionEngine.DEFAULT_INTERACT_DISTANCE, BlackboardKeys.ENTITY_TARGET),
|
||||||
new HarvestNode(),
|
new HarvestNode(),
|
||||||
@ -54,7 +66,7 @@ public class AcquireItemTree {
|
|||||||
new SequenceNode(
|
new SequenceNode(
|
||||||
new PublishStatusNode("Fell a tree"),
|
new PublishStatusNode("Fell a tree"),
|
||||||
//check if we should be sourcing this from felling a tree
|
//check if we should be sourcing this from felling a tree
|
||||||
new SourcingTypeNode(SourcingType.TREE),
|
new SourcingTypeNode(SourcingType.TREE, blackboardKey),
|
||||||
//TODO: logic to fell a tree
|
//TODO: logic to fell a tree
|
||||||
new RunnerNode(null)
|
new RunnerNode(null)
|
||||||
)
|
)
|
||||||
|
|||||||
216
src/main/java/electrosphere/server/player/CraftingActions.java
Normal file
216
src/main/java/electrosphere/server/player/CraftingActions.java
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
package electrosphere.server.player;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import electrosphere.engine.Globals;
|
||||||
|
import electrosphere.entity.Entity;
|
||||||
|
import electrosphere.entity.state.inventory.InventoryUtils;
|
||||||
|
import electrosphere.entity.state.inventory.RelationalInventoryState;
|
||||||
|
import electrosphere.entity.state.inventory.UnrelationalInventoryState;
|
||||||
|
import electrosphere.entity.state.item.ServerChargeState;
|
||||||
|
import electrosphere.game.data.crafting.RecipeData;
|
||||||
|
import electrosphere.game.data.crafting.RecipeIngredientData;
|
||||||
|
import electrosphere.game.data.item.Item;
|
||||||
|
import electrosphere.game.data.item.ItemDataMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actions around crafting
|
||||||
|
*/
|
||||||
|
public class CraftingActions {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to craft an item
|
||||||
|
* @param crafter The entity performing the crafting
|
||||||
|
* @param station The (optional) station for crafting
|
||||||
|
* @param recipe The recipe to craft
|
||||||
|
*/
|
||||||
|
public static void attemptCraft(Entity crafter, Entity station, RecipeData recipe){
|
||||||
|
if(InventoryUtils.serverGetInventoryState(crafter) == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UnrelationalInventoryState naturalInventory = InventoryUtils.getNaturalInventory(crafter);
|
||||||
|
RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(crafter);
|
||||||
|
|
||||||
|
//get data obj
|
||||||
|
ItemDataMap itemMap = Globals.gameConfigCurrent.getItemMap();
|
||||||
|
|
||||||
|
//get reagents
|
||||||
|
List<Entity> reagentList = new LinkedList<Entity>();
|
||||||
|
boolean hasReagents = true;
|
||||||
|
Map<String,Integer> ingredientTargetMap = new HashMap<String,Integer>();
|
||||||
|
Map<String,Integer> ingredientAccretionMap = new HashMap<String,Integer>();
|
||||||
|
//find the reagents we're going to use to craft
|
||||||
|
for(RecipeIngredientData ingredient : recipe.getIngredients()){
|
||||||
|
ingredientTargetMap.put(ingredient.getItemType(),ingredient.getCount());
|
||||||
|
ingredientAccretionMap.put(ingredient.getItemType(),0);
|
||||||
|
int found = 0;
|
||||||
|
if(naturalInventory != null){
|
||||||
|
for(Entity itemEnt : naturalInventory.getItems()){
|
||||||
|
if(itemMap.getItem(itemEnt).getId().matches(ingredient.getItemType())){
|
||||||
|
if(ServerChargeState.hasServerChargeState(itemEnt)){
|
||||||
|
ServerChargeState serverChargeState = ServerChargeState.getServerChargeState(itemEnt);
|
||||||
|
found = found + serverChargeState.getCharges();
|
||||||
|
} else {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
reagentList.add(itemEnt);
|
||||||
|
}
|
||||||
|
if(found >= ingredient.getCount()){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(toolbarInventory != null){
|
||||||
|
for(Entity itemEnt : toolbarInventory.getItems()){
|
||||||
|
if(itemEnt == null){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(itemMap.getItem(itemEnt).getId().matches(ingredient.getItemType())){
|
||||||
|
if(ServerChargeState.hasServerChargeState(itemEnt)){
|
||||||
|
ServerChargeState serverChargeState = ServerChargeState.getServerChargeState(itemEnt);
|
||||||
|
found = found + serverChargeState.getCharges();
|
||||||
|
} else {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
reagentList.add(itemEnt);
|
||||||
|
}
|
||||||
|
if(found >= ingredient.getCount()){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found < ingredient.getCount()){
|
||||||
|
hasReagents = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(hasReagents){
|
||||||
|
for(Entity reagentEnt : reagentList){
|
||||||
|
|
||||||
|
//determine how many we need to still remove
|
||||||
|
Item itemData = itemMap.getItem(reagentEnt);
|
||||||
|
int targetToRemove = ingredientTargetMap.get(itemData.getId());
|
||||||
|
int alreadyFound = ingredientAccretionMap.get(itemData.getId());
|
||||||
|
if(alreadyFound > targetToRemove){
|
||||||
|
throw new Error("Removed too many ingredients! " + targetToRemove + " " + alreadyFound);
|
||||||
|
} else if(alreadyFound == targetToRemove){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(ServerChargeState.hasServerChargeState(reagentEnt)){
|
||||||
|
ServerChargeState serverChargeState = ServerChargeState.getServerChargeState(reagentEnt);
|
||||||
|
int available = serverChargeState.getCharges();
|
||||||
|
|
||||||
|
if(available > targetToRemove - alreadyFound){
|
||||||
|
int chargesToRemove = targetToRemove - alreadyFound;
|
||||||
|
serverChargeState.attemptAddCharges(-chargesToRemove);
|
||||||
|
//just remove charges
|
||||||
|
ingredientAccretionMap.put(itemData.getId(),alreadyFound + chargesToRemove);
|
||||||
|
} else {
|
||||||
|
//remove item entirely (consuming all charges)
|
||||||
|
if(naturalInventory != null){
|
||||||
|
naturalInventory.removeItem(reagentEnt);
|
||||||
|
}
|
||||||
|
if(toolbarInventory != null){
|
||||||
|
toolbarInventory.tryRemoveItem(reagentEnt);
|
||||||
|
}
|
||||||
|
InventoryUtils.serverDestroyInventoryItem(reagentEnt);
|
||||||
|
ingredientAccretionMap.put(itemData.getId(),alreadyFound + available);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(naturalInventory != null){
|
||||||
|
naturalInventory.removeItem(reagentEnt);
|
||||||
|
}
|
||||||
|
if(toolbarInventory != null){
|
||||||
|
toolbarInventory.tryRemoveItem(reagentEnt);
|
||||||
|
}
|
||||||
|
InventoryUtils.serverDestroyInventoryItem(reagentEnt);
|
||||||
|
ingredientAccretionMap.put(itemData.getId(),alreadyFound + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(RecipeIngredientData product : recipe.getProducts()){
|
||||||
|
Item productType = itemMap.getItem(product.getItemType());
|
||||||
|
if(productType == null){
|
||||||
|
throw new Error("Could not locate product definition! " + productType + " " + product.getItemType());
|
||||||
|
}
|
||||||
|
InventoryUtils.serverCreateInventoryItem(crafter, product.getItemType(), product.getCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the item can be crafted
|
||||||
|
* @param crafter The entity performing the crafting
|
||||||
|
* @param workstation The workstation to perform the crafting at
|
||||||
|
* @param recipe The recipe to craft
|
||||||
|
* @return true if it can perform the recipe, false otherwise
|
||||||
|
*/
|
||||||
|
public static boolean canCraft(Entity crafter, Entity workstation, RecipeData recipe){
|
||||||
|
if(InventoryUtils.serverGetInventoryState(crafter) == null){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
UnrelationalInventoryState naturalInventory = InventoryUtils.getNaturalInventory(crafter);
|
||||||
|
RelationalInventoryState toolbarInventory = InventoryUtils.getToolbarInventory(crafter);
|
||||||
|
|
||||||
|
//get data obj
|
||||||
|
ItemDataMap itemMap = Globals.gameConfigCurrent.getItemMap();
|
||||||
|
|
||||||
|
//get reagents
|
||||||
|
List<Entity> reagentList = new LinkedList<Entity>();
|
||||||
|
boolean hasReagents = true;
|
||||||
|
Map<String,Integer> ingredientTargetMap = new HashMap<String,Integer>();
|
||||||
|
Map<String,Integer> ingredientAccretionMap = new HashMap<String,Integer>();
|
||||||
|
//find the reagents we're going to use to craft
|
||||||
|
for(RecipeIngredientData ingredient : recipe.getIngredients()){
|
||||||
|
ingredientTargetMap.put(ingredient.getItemType(),ingredient.getCount());
|
||||||
|
ingredientAccretionMap.put(ingredient.getItemType(),0);
|
||||||
|
int found = 0;
|
||||||
|
if(naturalInventory != null){
|
||||||
|
for(Entity itemEnt : naturalInventory.getItems()){
|
||||||
|
if(itemMap.getItem(itemEnt).getId().matches(ingredient.getItemType())){
|
||||||
|
if(ServerChargeState.hasServerChargeState(itemEnt)){
|
||||||
|
ServerChargeState serverChargeState = ServerChargeState.getServerChargeState(itemEnt);
|
||||||
|
found = found + serverChargeState.getCharges();
|
||||||
|
} else {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
reagentList.add(itemEnt);
|
||||||
|
}
|
||||||
|
if(found >= ingredient.getCount()){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(toolbarInventory != null){
|
||||||
|
for(Entity itemEnt : toolbarInventory.getItems()){
|
||||||
|
if(itemEnt == null){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(itemMap.getItem(itemEnt).getId().matches(ingredient.getItemType())){
|
||||||
|
if(ServerChargeState.hasServerChargeState(itemEnt)){
|
||||||
|
ServerChargeState serverChargeState = ServerChargeState.getServerChargeState(itemEnt);
|
||||||
|
found = found + serverChargeState.getCharges();
|
||||||
|
} else {
|
||||||
|
found++;
|
||||||
|
}
|
||||||
|
reagentList.add(itemEnt);
|
||||||
|
}
|
||||||
|
if(found >= ingredient.getCount()){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found < ingredient.getCount()){
|
||||||
|
hasReagents = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasReagents;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user