@ -13,21 +13,27 @@ import engine.Enum;
				@@ -13,21 +13,27 @@ import engine.Enum;
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.Enum.GameObjectType ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.Enum.ModType ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.Enum.SourceType ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.InterestManagement.WorldGrid ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.exception.MsgSendException ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.gameManager.BuildingManager ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.gameManager.ChatManager ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.gameManager.MovementManager ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.math.Bounds ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.math.Vector3fImmutable ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.mobileAI.Threads.MobAIThread ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.net.client.msg.MoveToPointMsg ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.objects.* ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  engine.server.MBServerStatics ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  org.pmw.tinylog.Logger ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  java.util.ArrayList ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import  java.util.concurrent.ThreadLocalRandom ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import static  engine.math.FastMath.sqr ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					import static  engine.math.FastMath.sqrt ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					public  class  MovementUtilities  {  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					private  static  final  int  cellGap  =  4 ;  
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    public  static  boolean  inRangeOfBindLocation ( Mob  agent )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
	
		
			
				
					
						
							
								 
							 
						
						
							
								 
							 
						
						
					 
				
				 
				 
				
					@ -291,5 +297,129 @@ public class MovementUtilities {
				@@ -291,5 +297,129 @@ public class MovementUtilities {
					 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    public  static  void  pathfind ( AbstractCharacter  character ,  Vector3fImmutable  goal ) {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        try  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ArrayList < Vector3fImmutable >  path  =  getOptimizedPath ( getPath ( character . loc ,  goal ) ,  getPath ( goal ,  character . loc ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if  ( path . isEmpty ( ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                ( ( Mob )  character ) . setDestination ( character . loc ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                return ;  //no points to walk to
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ( ( Mob )  character ) . destination  =  path . get ( 0 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }  catch ( Exception  e ) {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            //something failed
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    public  static  ArrayList < Vector3fImmutable >  getOptimizedPath ( ArrayList < Vector3fImmutable >  startToGoal ,  ArrayList < Vector3fImmutable >  goalToStart )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ArrayList < Vector3fImmutable >  optimalPath  =  new  ArrayList < > ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        optimalPath . add ( startToGoal . get ( 0 ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        for ( Vector3fImmutable  point  :  startToGoal )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            if ( ! goalToStart . contains ( point ) )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                continue ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            optimalPath . add ( point ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  optimalPath ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    private  static  ArrayList < Vector3fImmutable >  getPath ( Vector3fImmutable  start ,  Vector3fImmutable  goal )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        ArrayList < Vector3fImmutable >  path  =  new  ArrayList < > ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        path . add ( start ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        Vector3fImmutable  current  =  start ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        boolean  obstructed  =  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        while  ( current . distanceSquared ( goal )  >  9 )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            //gather the 8 cells around the player
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ArrayList < Vector3fImmutable >  surroundingCells  =  new  ArrayList < > ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            surroundingCells . add ( current . add ( new  Vector3fImmutable ( cellGap ,  0 ,  0 ) ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            surroundingCells . add ( current . add ( new  Vector3fImmutable ( cellGap ,  0 ,  cellGap ) ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            surroundingCells . add ( current . add ( new  Vector3fImmutable ( 0 ,  0 ,  cellGap ) ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            surroundingCells . add ( current . add ( new  Vector3fImmutable ( - cellGap ,  0 ,  0 ) ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            surroundingCells . add ( current . add ( new  Vector3fImmutable ( - cellGap ,  0 ,  - cellGap ) ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            surroundingCells . add ( current . add ( new  Vector3fImmutable ( 0 ,  0 ,  - cellGap ) ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            surroundingCells . add ( current . add ( new  Vector3fImmutable ( - cellGap ,  0 ,  cellGap ) ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            surroundingCells . add ( current . add ( new  Vector3fImmutable ( cellGap ,  0 ,  - cellGap ) ) ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            Vector3fImmutable  cheapest  =  new  Vector3fImmutable ( - 10000 ,  0 ,  - 10000 ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            for  ( Vector3fImmutable  point  :  surroundingCells )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( path . contains ( point ) )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    continue ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                Regions  region  =  Regions . getRegionAtLocation ( point ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if ( region  ! =  null )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    //if (!region.stairs)
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    //    point.setY(region.center.y);
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    //else
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    //    point.setY(region.lerpY(point));
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    path . add ( new  Vector3fImmutable ( region . center . x , region . center . y , region . center . z ) ) ;  //only use center points when travelling through regions
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    continue ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( pointIsBlocked ( point ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    obstructed  =  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    continue ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                if  ( getCost ( cheapest ,  current ,  goal )  >  getCost ( point ,  current ,  goal ) )   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					                    cheapest  =  point ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            current  =  cheapest ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            path . add ( cheapest ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if ( obstructed )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            return  path ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        } else  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ArrayList < Vector3fImmutable >  goalPath  =  new  ArrayList < > ( ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            goalPath . add ( goal ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            goalPath . add ( start ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            return  goalPath ;  //if the path isn't obstructed we can walk directly from start to the goal
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    public  static  float  getCost ( Vector3fImmutable  point ,  Vector3fImmutable  start ,  Vector3fImmutable  goal )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        float  gCost  =  start . distanceSquared ( point ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        float  hCost  =  goal . distanceSquared ( point ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  gCost  +  hCost ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    public  static  boolean  pointIsBlocked ( Vector3fImmutable  point )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        //TODO figure out best way to decide if a walking point intersects a mesh collider from a building
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        Building  building  =  BuildingManager . getBuildingAtLocation ( point ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if ( building  = =  null )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            printToPlayers ( point ,  "No Building Found At: "  +  point ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            return  false ; //no building at this location means nothing obstructing the walking path
   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if ( ! collidesWithBuilding ( building , point ) )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            printToPlayers ( point ,  "No Building Collision At: "  +  point ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            return  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        if ( Regions . getRegionAtLocation ( point )  ! =  null )  {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            printToPlayers ( point ,  "Region Found At: "  +  point ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            return  false ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        printToPlayers ( point ,  "Path Blocked At: "  +  point ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  true ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    private  static  boolean  collidesWithBuilding ( Building  building ,  Vector3fImmutable  end ) {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        MeshBounds  mb  =  Bounds . meshBoundsCache . get ( building . meshUUID ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        return  ( end . x  >  mb . minX  & &  end . x  <  mb . maxX  & &  end . z  >  mb . minZ  & &  end . z  <  mb . maxZ ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					
 
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    private  static  void  printToPlayers ( Vector3fImmutable  loc ,  String  message ) {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        for ( AbstractWorldObject  awo  :  WorldGrid . getObjectsInRangePartial ( loc ,  MBServerStatics . CHARACTER_LOAD_RANGE ,  MBServerStatics . MASK_PLAYER ) ) {   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            PlayerCharacter  pc  =  ( PlayerCharacter ) awo ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					            ChatManager . chatSystemInfo ( pc ,  message ) ;   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					        }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					    }   
				
			 
			
		
	
		
			
				
					 
					 
				
				 
				 
				
					}