package electrosphere.entity.state.equip; import electrosphere.net.synchronization.BehaviorTreeIdEnums; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.ode4j.ode.DBody; import electrosphere.engine.Globals; import electrosphere.entity.Entity; import electrosphere.entity.EntityDataStrings; import electrosphere.entity.EntityTags; import electrosphere.entity.EntityUtils; import electrosphere.entity.btree.BehaviorTree; import electrosphere.entity.state.gravity.GravityUtils; import electrosphere.entity.types.attach.AttachUtils; import electrosphere.entity.types.creature.CreatureUtils; import electrosphere.entity.types.item.ItemUtils; import electrosphere.game.data.creature.type.equip.EquipPoint; import electrosphere.game.data.item.type.EquipWhitelist; import electrosphere.logger.LoggerInterface; import electrosphere.net.parser.net.message.InventoryMessage; import electrosphere.net.parser.net.message.NetworkMessage; import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree; import electrosphere.renderer.actor.Actor; import electrosphere.renderer.actor.ActorMeshMask; @SynchronizedBehaviorTree(name = "clientEquipState", isServer = false, correspondingTree="serverEquipState") /** * Client view of items equipped to a given entity */ public class ClientEquipState implements BehaviorTree { //the parent entity of the btree Entity parent; //the list of available equip points List equipPoints = new LinkedList(); //the map of point to the equipped entity Map equipMap = new HashMap(); /** * Creates the tree * @param parent the entity this is attached to * @param equipPoints the list of available points */ private ClientEquipState(Entity parent, List equipPoints){ this.parent = parent; for(EquipPoint point : equipPoints){ this.equipPoints.add(point); } } /** * Gets the list of equipped points * @return the list */ public List getEquippedPoints(){ return new LinkedList(equipMap.keySet()); } /** * Gets the list of all equip points * @return The list of all equip points */ public List getAllEquipPoints(){ return equipPoints; } /** * Attempts to equip the item * @param toEquip the item to equip * @param point the point to equip to */ public void commandAttemptEquip(Entity toEquip, EquipPoint point){ boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId()); boolean targetIsItem = ItemUtils.isItem(toEquip); boolean targetIsAttached = AttachUtils.isAttached(toEquip); String equipItemClass = ItemUtils.getEquipClass(toEquip); List pointEquipClassList = point.getEquipClassWhitelist(); boolean itemIsInPointWhitelist = pointEquipClassList.contains(equipItemClass); if(!hasEquipped && targetIsItem && !targetIsAttached && itemIsInPointWhitelist){ //send packet to server requesting to equip String pointName = point.getEquipPointId(); int serverSideID = Globals.clientSceneWrapper.mapClientToServerId(toEquip.getId()); NetworkMessage requestPickupMessage = InventoryMessage.constructclientRequestEquipItemMessage(pointName, serverSideID); Globals.clientConnection.queueOutgoingMessage(requestPickupMessage); } } /** * Performs the actual logic to term meshes on/off when equpping an item * @param toEquip The entity to equip * @param point The equipment point to equip to */ public void attemptEquip(Entity toEquip, EquipPoint point){ boolean hasEquipped = hasEquippedAtPoint(point.getEquipPointId()); boolean targetIsItem = ItemUtils.isItem(toEquip); boolean targetIsAttached = AttachUtils.isAttached(toEquip); boolean targetHasWhitelist = ItemUtils.hasEquipList(toEquip); String equipItemClass = ItemUtils.getEquipClass(toEquip); List pointEquipClassList = point.getEquipClassWhitelist(); boolean itemIsInPointWhitelist = pointEquipClassList.contains(equipItemClass); if(!hasEquipped && targetIsItem && !targetIsAttached && itemIsInPointWhitelist){ // //visual transforms if(targetHasWhitelist){ //depends on the type of creature, must be replacing a mesh String parentCreatureId = CreatureUtils.getType(parent); List whitelist = ItemUtils.getEquipWhitelist(toEquip); for(EquipWhitelist whitelistItem : whitelist){ if(whitelistItem.getCreatureId().equals(parentCreatureId)){ //put in map equipMap.put(point.getEquipPointId(),toEquip); String modelName = whitelistItem.getModel(); Globals.assetManager.addModelPathToQueue(modelName); Actor parentActor = EntityUtils.getActor(parent); //queue meshes from display model to parent actor ActorMeshMask meshMask = parentActor.getMeshMask(); for(String toBlock : whitelistItem.getMeshMaskList()){ meshMask.blockMesh(modelName, toBlock); } for(String toDraw : whitelistItem.getMeshList()){ meshMask.queueMesh(modelName, toDraw); } //attach to parent bone AttachUtils.clientAttachEntityToEntityAtBone(parent, toEquip, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationThirdPerson())); //make uncollidable if(toEquip.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && toEquip.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){ DBody rigidBody = (DBody)toEquip.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); Globals.clientSceneWrapper.getCollisionEngine().deregisterPhysicsObject(rigidBody); } //hide toEquip actor EntityUtils.setDraw(toEquip, false); //make untargetable Globals.clientSceneWrapper.getScene().removeEntityFromTag(toEquip, EntityTags.TARGETABLE); break; } } } else { //does not depend on the type of creature, must be attaching to a bone equipMap.put(point.getEquipPointId(),toEquip); if(Globals.controlHandler.cameraIsThirdPerson()){ AttachUtils.clientAttachEntityToEntityAtBone(parent, toEquip, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationThirdPerson())); } else { AttachUtils.clientAttachEntityToEntityAtBone(Globals.firstPersonEntity, toEquip, point.getFirstPersonBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationFirstPerson())); } if(toEquip.containsKey(EntityDataStrings.PHYSICS_COLLISION_BODY) && toEquip.containsKey(EntityDataStrings.PHYSICS_COLLIDABLE)){ DBody rigidBody = (DBody)toEquip.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); Globals.clientSceneWrapper.getCollisionEngine().deregisterPhysicsObject(rigidBody); } Globals.clientSceneWrapper.getScene().removeEntityFromTag(toEquip, EntityTags.TARGETABLE); GravityUtils.clientAttemptDeactivateGravity(toEquip); } } // if(!hasEquipPrimary() && ItemUtils.isItem(toEquip) && !AttachUtils.isAttached(toEquip)){ // if(ItemUtils.hasEquipList(toEquip)){ // String parentCreatureId = CreatureUtils.getType(parent); // List whitelist = ItemUtils.getEquipWhitelist(toEquip); // for(EquipWhitelist whitelistItem : whitelist){ // if(whitelistItem.getCreatureId().equals(parentCreatureId)){ // equipPrimary = toEquip; // String modelName = whitelistItem.getModel(); // Globals.assetManager.addModelPathToQueue(modelName); // Actor parentActor = EntityUtils.getActor(parent); // //queue meshes from display model to parent actor // ActorMeshMask meshMask = parentActor.getMeshMask(); // for(String toBlock : whitelistItem.getMeshMaskList()){ // meshMask.blockMesh(modelName, toBlock); // } // for(String toDraw : whitelistItem.getMeshList()){ // meshMask.queueMesh(modelName, toDraw); // } // //attach to parent bone // AttachUtils.attachEntityToEntityAtBone(parent, toEquip, equipPrimaryBoneName); // //make uncollidable // if(toEquip.getDataKeys().contains(EntityDataStrings.PHYSICS_COLLISION_BODY) && toEquip.getDataKeys().contains(EntityDataStrings.PHYSICS_COLLIDABLE)){ // CollisionObject rigidBody = (CollisionObject)toEquip.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); // Globals.collisionEngine.deregisterPhysicsObject(rigidBody); // } // //hide toEquip actor // EntityUtils.setDraw(toEquip, false); // //make untargetable // Globals.entityManager.setTargetable(equipPrimary, false); // break; // } // } // } else { // equipPrimary = toEquip; // AttachUtils.attachEntityToEntityAtBone(parent, toEquip, equipPrimaryBoneName); // if(toEquip.getDataKeys().contains(EntityDataStrings.PHYSICS_COLLISION_BODY) && toEquip.getDataKeys().contains(EntityDataStrings.PHYSICS_COLLIDABLE)){ // CollisionObject rigidBody = (CollisionObject)toEquip.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); // Globals.collisionEngine.deregisterPhysicsObject(rigidBody); // } // Globals.entityManager.setTargetable(equipPrimary, false); // } // } } /** * Gets the equip point by its name * @param name the name of the equip point * @return the equip point object if it exists, otherwise null */ public EquipPoint getEquipPoint(String name){ for(EquipPoint point : equipPoints){ if(point.getEquipPointId().equals(name)){ return point; } } return null; } /** * Gets the item equipped at a point * @param point the point's name * @return the item entity */ public Entity getEquippedItemAtPoint(String point){ return equipMap.get(point); } /** * Returns whether the entity has an equip state * @param entity The entity to check * @return True if the entity contains an equip state, false otherwise */ public static boolean hasEquipState(Entity entity){ return entity.containsKey(EntityDataStrings.TREE_CLIENTEQUIPSTATE); } /** * Gets the equip state on the entity * @param entity The entity to retrieve equip state from * @return The equip state on the entity */ public static ClientEquipState getEquipState(Entity entity){ return (ClientEquipState)entity.getData(EntityDataStrings.TREE_CLIENTEQUIPSTATE); } /** * Sets the equip state on the entity * @param entity The entity to attach the equip state to * @param equipState The equip state to attach */ public static void setEquipState(Entity entity, ClientEquipState equipState){ entity.putData(EntityDataStrings.TREE_CLIENTEQUIPSTATE, equipState); } // public void drop(Entity entity){ // if(hasEquipPrimary()){ // AttachUtils.detatchEntityFromEntityAtBone(parent,equipPrimary); // if(equipPrimary.getDataKeys().contains(EntityDataStrings.PHYSICS_COLLISION_BODY) && equipPrimary.getDataKeys().contains(EntityDataStrings.PHYSICS_COLLIDABLE)){ // CollisionObject rigidBody = (CollisionObject)equipPrimary.getData(EntityDataStrings.PHYSICS_COLLISION_BODY); // Globals.collisionEngine.registerPhysicsObject(rigidBody); // } // Globals.entityManager.setTargetable(equipPrimary, true); // equipPrimary = null; // } // } /** * Attempts to unequip the item at a given point * @param pointId the id of the point */ public void commandAttemptUnequip(String pointId){ boolean hasEquipped = hasEquippedAtPoint(pointId); if(hasEquipped){ //send packet to server requesting to equip NetworkMessage requestUnequipMessage = InventoryMessage.constructclientRequestUnequipItemMessage(pointId); Globals.clientConnection.queueOutgoingMessage(requestUnequipMessage); } } /** * Performs the actual logic to turn meshes on/off when unequipping an item * @param pointId The equipment point to unequip */ public void clientTransformUnequipPoint(String pointId){ Entity equipped = equipMap.remove(pointId); if(equipped != null){ boolean targetHasWhitelist = ItemUtils.hasEquipList(equipped); // //visual transforms if(targetHasWhitelist){ //depends on the type of creature, must be replacing meshes String parentCreatureId = CreatureUtils.getType(parent); List whitelist = ItemUtils.getEquipWhitelist(equipped); for(EquipWhitelist whitelistItem : whitelist){ if(whitelistItem.getCreatureId().equals(parentCreatureId)){ //put in map Actor parentActor = EntityUtils.getActor(parent); //queue meshes from display model to parent actor ActorMeshMask meshMask = parentActor.getMeshMask(); for(String toUnblock : whitelistItem.getMeshMaskList()){ meshMask.unblockMesh(toUnblock); } for(String toDraw : whitelistItem.getMeshList()){ meshMask.removeAdditionalMesh(toDraw); } break; } } } else { //does not depend on the type of creature AttachUtils.clientDetatchEntityFromEntityAtBone(parent, equipped); EntityUtils.cleanUpEntity(equipped); } } } /** * Checks if a point has an item equipped * @param point the equip point * @return true if there is an item equipped, false otherwise */ public boolean hasEquippedAtPoint(String point){ return equipMap.containsKey(point); } /** * Checks if the player has any attached entities, and if so, makes sure they're attached to the right model * This should be used when we change the camera of the player (IE from first to third person or vice versa) */ public void evaluatePlayerAttachments(){ if(this.parent != Globals.playerEntity){ LoggerInterface.loggerEngine.ERROR(new IllegalStateException("Re-evaluating client attachments on non-player entity! This should only be called for the player's entity!")); } if(Globals.controlHandler.cameraIsThirdPerson()){ for(String occupiedPoint : this.getEquippedPoints()){ EquipPoint point = this.getEquipPoint(occupiedPoint); Entity toEquip = this.equipMap.get(point.getEquipPointId()); if(AttachUtils.getParent(toEquip) != Globals.playerEntity){ AttachUtils.clientDetatchEntityFromEntityAtBone(Globals.firstPersonEntity, toEquip); AttachUtils.clientAttachEntityToEntityAtBone(Globals.playerEntity, toEquip, point.getBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationThirdPerson())); } else { AttachUtils.clientUpdateEntityTransforms(toEquip, Globals.playerEntity); } } } else { for(String occupiedPoint : this.getEquippedPoints()){ EquipPoint point = this.getEquipPoint(occupiedPoint); Entity toEquip = this.equipMap.get(point.getEquipPointId()); if(AttachUtils.getParent(toEquip) != Globals.firstPersonEntity){ AttachUtils.clientDetatchEntityFromEntityAtBone(Globals.playerEntity, toEquip); AttachUtils.clientAttachEntityToEntityAtBone(Globals.firstPersonEntity, toEquip, point.getFirstPersonBone(), AttachUtils.getEquipPointRotationOffset(point.getOffsetRotationFirstPerson())); } else { AttachUtils.clientUpdateEntityTransforms(toEquip, Globals.firstPersonEntity); } } } } @Override public void simulate(float deltaTime) { } /** *

(initially) Automatically generated

*

More parameters can be safely added to this method

*

* Attaches this tree to the entity. *

* @param entity The entity to attach to * @param tree The behavior tree to attach */ public static ClientEquipState attachTree(Entity parent, List equipPoints){ ClientEquipState rVal = new ClientEquipState(parent, equipPoints); //put manual code here (setting params, etc) //!!WARNING!! from here below should not be touched //This was generated automatically to properly alert various systems that the btree exists and should be tracked parent.putData(EntityDataStrings.TREE_CLIENTEQUIPSTATE, rVal); Globals.clientScene.registerBehaviorTree(rVal); Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_CLIENTEQUIPSTATE_ID); return rVal; } /** *

Automatically generated

*

* Detatches this tree from the entity. *

* @param entity The entity to detach to * @param tree The behavior tree to detach */ public static void detachTree(Entity entity, BehaviorTree tree){ Globals.entityValueTrackingService.detatchTreeFromEntity(entity, BehaviorTreeIdEnums.BTREE_CLIENTEQUIPSTATE_ID); } /** *

* Gets the ClientEquipState of the entity *

* @param entity the entity * @return The ClientEquipState */ public static ClientEquipState getClientEquipState(Entity entity){ return (ClientEquipState)entity.getData(EntityDataStrings.TREE_CLIENTEQUIPSTATE); } }