300 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			300 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package electrosphere.entity.state.gravity;
 | |
| 
 | |
| 
 | |
| import electrosphere.entity.EntityDataStrings;
 | |
| 
 | |
| import electrosphere.net.synchronization.BehaviorTreeIdEnums;
 | |
| import electrosphere.net.parser.net.message.SynchronizationMessage;
 | |
| import electrosphere.server.datacell.utils.DataCellSearchUtils;
 | |
| import electrosphere.server.datacell.utils.ServerBehaviorTreeUtils;
 | |
| 
 | |
| import java.util.List;
 | |
| import java.util.concurrent.CopyOnWriteArrayList;
 | |
| 
 | |
| import org.joml.Quaterniond;
 | |
| import org.joml.Quaternionf;
 | |
| import org.joml.Vector3d;
 | |
| import org.joml.Vector3f;
 | |
| import org.ode4j.ode.DBody;
 | |
| 
 | |
| import electrosphere.collision.collidable.Collidable;
 | |
| import electrosphere.engine.Globals;
 | |
| import electrosphere.entity.Entity;
 | |
| import electrosphere.entity.EntityUtils;
 | |
| import electrosphere.entity.state.BehaviorTree;
 | |
| import electrosphere.entity.state.collidable.Impulse;
 | |
| import electrosphere.entity.state.collidable.ServerCollidableTree;
 | |
| import electrosphere.entity.state.gravity.ClientGravityTree.GravityTreeState;
 | |
| import electrosphere.entity.state.movement.ServerFallTree;
 | |
| import electrosphere.entity.state.movement.ServerJumpTree;
 | |
| import electrosphere.net.parser.net.message.EntityMessage;
 | |
| import electrosphere.net.synchronization.annotation.SyncedField;
 | |
| import electrosphere.net.synchronization.annotation.SynchronizedBehaviorTree;
 | |
| import electrosphere.server.datacell.Realm;
 | |
| 
 | |
| @SynchronizedBehaviorTree(name = "serverGravity", isServer = true, correspondingTree="gravity")
 | |
| /**
 | |
|  * Tree for making the entity fall if there's nothing underneath it
 | |
|  */
 | |
| public class ServerGravityTree implements BehaviorTree {
 | |
|     
 | |
|     @SyncedField
 | |
|     GravityTreeState state;
 | |
|     
 | |
|     Entity parent;
 | |
| 
 | |
|     int frameCurrent = 0;
 | |
|     int fallFrame = 1;
 | |
|     
 | |
|     float gravityVelocity = 0;
 | |
|     float gravityAccel = 0.0007f;
 | |
|     
 | |
|     DBody body;
 | |
|     Collidable collidable;
 | |
|     
 | |
|     List<EntityMessage> networkMessageQueue = new CopyOnWriteArrayList<EntityMessage>();
 | |
|     
 | |
|     private ServerGravityTree(Entity e, Collidable collidable, DBody body, int fallFrame){
 | |
|         state = GravityTreeState.ACTIVE;
 | |
|         parent = e;
 | |
|         this.body = body;
 | |
|         this.collidable = collidable;
 | |
|         this.fallFrame = fallFrame;
 | |
|     }
 | |
|     
 | |
| //    public void setCollisionObject(CollisionObject body, Collidable collidable){
 | |
| //        this.body = body;
 | |
| //        this.collidable = collidable;
 | |
| //    }
 | |
|     
 | |
|     /**
 | |
|      * <p> Automatically generated </p>
 | |
|      * <p>
 | |
|      * Gets state.
 | |
|      * </p>
 | |
|      */
 | |
|     public GravityTreeState getState(){
 | |
|         return state;
 | |
|     }
 | |
|     
 | |
|     public void start(){
 | |
|         //TODO: check if can start moving
 | |
|         setState(GravityTreeState.ACTIVE);
 | |
|         if(state == GravityTreeState.NOT_ACTIVE){
 | |
|             frameCurrent = 0;
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     public void interrupt(){
 | |
|         setState(GravityTreeState.NOT_ACTIVE);
 | |
|     }
 | |
|     
 | |
|     public void stop(){
 | |
|         setState(GravityTreeState.NOT_ACTIVE);
 | |
|     }
 | |
|     
 | |
|     static final float gravityConstant = 0.2f;
 | |
|     static final float linearDamping = 0.1f;
 | |
|     
 | |
|     public void simulate(float deltaTime){
 | |
| //        float velocity = CreatureUtils.getVelocity(parent);
 | |
| //        float acceleration = CreatureUtils.getAcceleration(parent);
 | |
| //        float maxNaturalVelocity = CreatureUtils.getMaxNaturalVelocity(parent);
 | |
| //        Actor entityActor = EntityUtils.getActor(parent);
 | |
|         Vector3d position = EntityUtils.getPosition(parent);
 | |
| //        Vector3f movementVector = CreatureUtils.getMovementVector(parent);
 | |
|         Quaterniond rotation = EntityUtils.getRotation(parent);
 | |
|         Vector3f newPosition;
 | |
|         ServerCollidableTree collidableTree = null;
 | |
|         if(ServerCollidableTree.hasServerCollidableTree(parent)){
 | |
|             collidableTree = ServerCollidableTree.getServerCollidableTree(parent);
 | |
|         }
 | |
| 
 | |
|         //parse attached network messages
 | |
| //        for(EntityMessage message : networkMessageQueue){
 | |
| //            networkMessageQueue.remove(message);
 | |
| ////            System.out.println("MOVE to " + message.getX() + " " + message.getY() + " " + message.getZ());
 | |
| //            switch(message.getMessageSubtype()){
 | |
| //                case ATTACKUPDATE:
 | |
| //                    switch(message.gettreeState()){
 | |
| //                     case 0:
 | |
| //                            state = IdleTreeState.IDLE;
 | |
| //                            break;
 | |
| //                        case 1:
 | |
| //                            state = IdleTreeState.NOT_IDLE;
 | |
| //                            break;
 | |
| //                    }
 | |
| //                    EntityUtils.getPosition(parent).set(message.getpositionX(),message.getpositionY(),message.getpositionZ());
 | |
| //                    CreatureUtils.setMovementVector(parent, new Vector3f(message.getrotationX(),message.getrotationY(),message.getrotationZ()));
 | |
| //                    break;
 | |
| //            }
 | |
| //        }
 | |
| 
 | |
|         //Basically if we're still spinning keep applying gravity
 | |
|         boolean angularVelocityLow = true;
 | |
|         if(collidableTree != null){
 | |
|             if(collidableTree.getAngularVelocityMagnitude() > 0.0001){
 | |
|                 angularVelocityLow = false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         
 | |
|         //state machine
 | |
|         switch(state){
 | |
|             case ACTIVE:
 | |
|                 if(hadGroundCollision()){
 | |
|                     setState(GravityTreeState.NOT_ACTIVE);
 | |
|                     if(!hadStructureCollision()){
 | |
| //                        position.set(new Vector3d(position.x,Globals.commonWorldData.getElevationAtPoint(position) + 0.0001f,position.z));
 | |
|                     }
 | |
|                     ServerJumpTree jumpTree;
 | |
|                     if((jumpTree = ServerJumpTree.getServerJumpTree(parent))!=null){
 | |
|                         jumpTree.land();
 | |
|                     }
 | |
|                     ServerFallTree fallTree;
 | |
|                     if((fallTree = ServerFallTree.getFallTree(parent))!=null){
 | |
|                         fallTree.land();
 | |
|                     }
 | |
|                     frameCurrent = 0;
 | |
|                     gravityVelocity = 0;
 | |
|                 } else {
 | |
|                     //animation nonsense
 | |
|                     frameCurrent++;
 | |
|                     if(frameCurrent == fallFrame){
 | |
|                         ServerFallTree fallTree;
 | |
|                         if((fallTree = ServerFallTree.getFallTree(parent))!=null){
 | |
|                             fallTree.start();
 | |
|                         }
 | |
|                     }
 | |
| 
 | |
|                     //actual gravity calculations
 | |
|                     if(gravityVelocity < gravityConstant){
 | |
|                         gravityVelocity = gravityVelocity + gravityAccel;
 | |
|                     }
 | |
|                     if(gravityVelocity > gravityConstant){
 | |
|                         gravityVelocity = gravityConstant;
 | |
|                     }
 | |
|                     float gravityDif = gravityVelocity * (float)Math.pow(1.0f - linearDamping,deltaTime * 2);
 | |
|                     // Vector3d newGravityPos = new Vector3d(position.x,position.y - gravityDif,position.z);
 | |
|                     // Realm parentRealm = Globals.realmManager.getEntityRealm(parent);
 | |
|                     // float hitFraction = parentRealm.getCollisionEngine().sweepTest(body, new Vector3f((float)position.x,(float)position.y,(float)position.z), new Vector3f((float)newGravityPos.x,(float)newGravityPos.y,(float)newGravityPos.z));
 | |
| //                    if(hitFraction >= 0){
 | |
| //                        collidable.addImpulse(new Impulse(new Vector3d(0,-1,0),gravityDif * hitFraction,"gravity"));
 | |
| //                        position.set(new Vector3d(position.x,position.y - gravityDif * hitFraction,position.z));
 | |
| //                    } else {
 | |
| //                        position.set(new Vector3d(position.x,position.y - gravityDif,position.z));
 | |
| //                    }
 | |
|                     // if(hitFraction < 0){
 | |
|                     //     hitFraction = 1;
 | |
|                     // }
 | |
|                     collidable.addImpulse(new Impulse(new Vector3d(0,-1,0), new Vector3d(0,0,0), new Vector3d(position), gravityDif,"gravity"));
 | |
|                 }
 | |
|                 break;
 | |
|             case NOT_ACTIVE:
 | |
|                 if(hadEntityCollision()){
 | |
|                     start();
 | |
|                 }
 | |
|                 //nothing here atm
 | |
|                 //eventually want to check if need to re-activate somehow
 | |
|                 break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public void addNetworkMessage(EntityMessage networkMessage) {
 | |
|         networkMessageQueue.add(networkMessage);
 | |
|     }
 | |
|     
 | |
|     public boolean hadStructureCollision(){
 | |
|         boolean rVal = false;
 | |
|         for(Impulse impulse : collidable.getImpulses()){
 | |
|             if(impulse.getType().equals(Collidable.TYPE_STRUCTURE)){
 | |
|                 rVal = true;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         return rVal;
 | |
|     }
 | |
|     
 | |
|     public boolean hadGroundCollision(){
 | |
|         boolean rVal = false;
 | |
|         for(Impulse impulse : collidable.getImpulses()){
 | |
|             if(impulse.getType().equals(Collidable.TYPE_TERRAIN)){
 | |
|                 rVal = true;
 | |
|                 break;
 | |
|             } else if(
 | |
|                     impulse.getType().equals(Collidable.TYPE_STRUCTURE) &&
 | |
|                     new Vector3d(impulse.getDirection()).normalize().y > 0.7
 | |
|                     ){
 | |
|                 rVal = true;
 | |
|             }
 | |
|         }
 | |
|         return rVal;
 | |
|     }
 | |
|     
 | |
|     public boolean hadEntityCollision(){
 | |
|         boolean rVal = false;
 | |
|         for(Impulse impulse : collidable.getImpulses()){
 | |
|             if(impulse.getType().equals(Collidable.TYPE_CREATURE)){
 | |
|                 rVal = true;
 | |
|                 break;
 | |
|             }
 | |
|         }
 | |
|         return rVal;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * <p> Automatically generated </p>
 | |
|      * <p>
 | |
|      * Sets state and handles the synchronization logic for it.
 | |
|      * </p>
 | |
|      * @param state The value to set state to.
 | |
|      */
 | |
|     public void setState(GravityTreeState state){
 | |
|         this.state = state;
 | |
|         int value = ClientGravityTree.getGravityTreeStateEnumAsShort(state);
 | |
|         DataCellSearchUtils.getEntityDataCell(parent).broadcastNetworkMessage(SynchronizationMessage.constructUpdateClientStateMessage(parent.getId(), 1, 1, value));
 | |
|     }
 | |
|     /**
 | |
|      * <p> (initially) Automatically generated </p>
 | |
|      * <p> More parameters can be safely added to this method</p>
 | |
|      * <p>
 | |
|      * Attaches this tree to the entity.
 | |
|      * </p>
 | |
|      * @param entity The entity to attach to
 | |
|      * @param tree The behavior tree to attach
 | |
|      */
 | |
|     public static ServerGravityTree attachTree(Entity parent, Collidable collidable, DBody body, int fallFrame){
 | |
|         ServerGravityTree rVal = new ServerGravityTree(parent,collidable,body,fallFrame);
 | |
|         //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
 | |
|         ServerBehaviorTreeUtils.attachBTreeToEntity(parent, rVal);
 | |
|         parent.putData(EntityDataStrings.TREE_SERVERGRAVITY, rVal);
 | |
|         Globals.entityValueTrackingService.attachTreeToEntity(parent, BehaviorTreeIdEnums.BTREE_SERVERGRAVITY_ID);
 | |
|         return rVal;
 | |
|     }
 | |
|     /**
 | |
|      * <p> Automatically generated </p>
 | |
|      * <p>
 | |
|      * Detatches this tree from the entity.
 | |
|      * </p>
 | |
|      * @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_SERVERGRAVITY_ID);
 | |
|     }
 | |
|     /**
 | |
|      * <p>
 | |
|      * Gets the ServerGravityTree of the entity
 | |
|      * </p>
 | |
|      * @param entity the entity
 | |
|      * @return The ServerGravityTree
 | |
|      */
 | |
|     public static ServerGravityTree getServerGravityTree(Entity entity){
 | |
|         return (ServerGravityTree)entity.getData(EntityDataStrings.TREE_SERVERGRAVITY);
 | |
|     }
 | |
| }
 |