예제 #1
0
        /// <summary>
        /// Gets the 1-voxel shell of a bounding box.
        /// </summary>
        /// <param name="box">The box.</param>
        /// <returns>A list of points on the boundary of the box.</returns>
        private IEnumerable <GlobalVoxelCoordinate> EnumerateShell(BoundingBox box)
        {
            int minX = MathFunctions.FloorInt(box.Min.X + 0.5f);
            int minY = MathFunctions.FloorInt(box.Min.Y + 0.5f);
            int minZ = MathFunctions.FloorInt(box.Min.Z + 0.5f);
            int maxX = MathFunctions.FloorInt(box.Max.X - 0.5f);
            int maxY = MathFunctions.FloorInt(box.Max.Y - 0.5f);
            int maxZ = MathFunctions.FloorInt(box.Max.Z - 0.5f);

            for (var y = minY; y <= maxY; y++)
            {
                // yx planes
                for (var z = minZ; z <= maxZ; z++)
                {
                    yield return(new GlobalVoxelCoordinate(minX, y, z));

                    yield return(new GlobalVoxelCoordinate(maxX, y, z));
                }
                // yz planes
                for (var x = minX + 1; x < maxX; x++)
                {
                    yield return(new GlobalVoxelCoordinate(x, y, minZ));

                    yield return(new GlobalVoxelCoordinate(x, y, maxZ));
                }
            }
        }
예제 #2
0
        public void GetItemsInBox <TObject>(BoundingBox box, HashSet <TObject> items) where TObject : T
        {
            Point3 minPoint = new Point3(MathFunctions.FloorInt(box.Min.X), MathFunctions.FloorInt(box.Min.Y), MathFunctions.FloorInt(box.Min.Z));
            Point3 maxPoint = new Point3(MathFunctions.FloorInt(box.Max.X), MathFunctions.FloorInt(box.Max.Y), MathFunctions.FloorInt(box.Max.Z));
            Point3 iter     = new Point3();

            for (iter.X = minPoint.X; iter.X <= maxPoint.X; iter.X++)
            {
                for (iter.Y = minPoint.Y; iter.Y <= maxPoint.Y; iter.Y++)
                {
                    for (iter.Z = minPoint.Z; iter.Z <= maxPoint.Z; iter.Z++)
                    {
                        List <T> itemsInVoxel = GetItems(iter);

                        if (itemsInVoxel == null)
                        {
                            continue;
                        }

                        foreach (TObject item in itemsInVoxel.OfType <TObject>())
                        {
                            items.Add(item);
                        }
                    }
                }
            }
        }
예제 #3
0
        public IEnumerable <GlobalVoxelCoordinate> Select(BoundingBox Bounds, Vector3 Start, Vector3 End, bool Invert)
        {
            int minX = MathFunctions.FloorInt(Bounds.Min.X + 0.5f);
            int minY = MathFunctions.FloorInt(Bounds.Min.Y + 0.5f);
            int minZ = MathFunctions.FloorInt(Bounds.Min.Z + 0.5f);
            int maxX = MathFunctions.FloorInt(Bounds.Max.X - 0.5f);
            int maxY = MathFunctions.FloorInt(Bounds.Max.Y - 0.5f);
            int maxZ = MathFunctions.FloorInt(Bounds.Max.Z - 0.5f);

            for (var y = minY; y <= maxY; y++)
            {
                // yx planes
                for (var z = minZ; z <= maxZ; z++)
                {
                    yield return(new GlobalVoxelCoordinate(minX, y, z));

                    yield return(new GlobalVoxelCoordinate(maxX, y, z));
                }
                // yz planes
                for (var x = minX + 1; x < maxX; x++)
                {
                    yield return(new GlobalVoxelCoordinate(x, y, minZ));

                    yield return(new GlobalVoxelCoordinate(x, y, maxZ));
                }
            }
        }
예제 #4
0
        public Vector3 RoundToChunkCoords(Vector3 location)
        {
            int x = MathFunctions.FloorInt(location.X * InvCSX);
            int y = MathFunctions.FloorInt(location.Y * InvCSY);
            int z = MathFunctions.FloorInt(location.Z * InvCSZ);

            return(new Vector3(x, y, z));
        }
예제 #5
0
        /// <summary>
        /// Gets the 1-voxel shell of a bounding box.
        /// </summary>
        /// <param name="box">The box.</param>
        /// <returns>A list of points on the boundary of the box.</returns>
        private IEnumerable <Vector3> GetShell(BoundingBox box)
        {
            int minX = MathFunctions.FloorInt(box.Min.X + 0.5f);
            int minY = MathFunctions.FloorInt(box.Min.Y + 0.5f);
            int minZ = MathFunctions.FloorInt(box.Min.Z + 0.5f);
            int maxX = MathFunctions.FloorInt(box.Max.X - 0.5f);
            int maxY = MathFunctions.FloorInt(box.Max.Y - 0.5f);
            int maxZ = MathFunctions.FloorInt(box.Max.Z - 0.5f);

            for (int y = minY; y <= maxY; y++)
            {
                // yx planes
                for (int z = minZ; z <= maxZ; z++)
                {
                    yield return(new Vector3(minX + 0.5f, y + 0.5f, z + 0.5f));

                    yield return(new Vector3(maxX + 0.5f, y + 0.5f, z + 0.5f));
                }
                // yz planes
                for (int x = minX; x <= maxX; x++)
                {
                    yield return(new Vector3(x + 0.5f, y + 0.5f, minZ + 0.5f));

                    yield return(new Vector3(x + 0.5f, y + 0.5f, maxZ + 0.5f));
                }
            }


            /*
             * if (maxY - minY > 1)
             * {
             *  for (int x = minX; x < maxX; x++)
             *  {
             *      // xz planes
             *      for (int z = minZ; z < maxZ; z++)
             *      {
             *          yield return new Vector3(x + 0.5f, minY + 0.5f, z + 0.5f);
             *          yield return new Vector3(x + 0.5f, maxY + 0.5f, z + 0.5f);
             *      }
             *  }
             * }
             */
        }
예제 #6
0
        public void RemoveObject(IBoundedObject bounded, BoundingBox oldLocation, CollisionType type)
        {
            if (type == CollisionType.None)
            {
                return;
            }
            Point3 minPoint = new Point3(MathFunctions.FloorInt(oldLocation.Min.X), MathFunctions.FloorInt(oldLocation.Min.Y), MathFunctions.FloorInt(oldLocation.Min.Z));
            Point3 maxPoint = new Point3(MathFunctions.FloorInt(oldLocation.Max.X), MathFunctions.FloorInt(oldLocation.Max.Y), MathFunctions.FloorInt(oldLocation.Max.Z));
            Point3 iter     = new Point3();

            for (iter.X = minPoint.X; iter.X <= maxPoint.X; iter.X++)
            {
                for (iter.Y = minPoint.Y; iter.Y <= maxPoint.Y; iter.Y++)
                {
                    for (iter.Z = minPoint.Z; iter.Z <= maxPoint.Z; iter.Z++)
                    {
                        Hashes[type].RemoveItem(iter, bounded);
                    }
                }
            }
        }
예제 #7
0
        public void AddObject(IBoundedObject bounded, CollisionType type)
        {
            if (type == CollisionType.None)
            {
                return;
            }
            BoundingBox box      = bounded.GetBoundingBox();
            Point3      minPoint = new Point3(MathFunctions.FloorInt(box.Min.X), MathFunctions.FloorInt(box.Min.Y), MathFunctions.FloorInt(box.Min.Z));
            Point3      maxPoint = new Point3(MathFunctions.FloorInt(box.Max.X), MathFunctions.FloorInt(box.Max.Y), MathFunctions.FloorInt(box.Max.Z));
            Point3      iter     = new Point3();

            for (iter.X = minPoint.X; iter.X <= maxPoint.X; iter.X++)
            {
                for (iter.Y = minPoint.Y; iter.Y <= maxPoint.Y; iter.Y++)
                {
                    for (iter.Z = minPoint.Z; iter.Z <= maxPoint.Z; iter.Z++)
                    {
                        Hashes[type].AddItem(iter, bounded);
                    }
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Gets a stairstep stretching accross the box.
        /// </summary>
        /// <param name="box">The box.</param>
        /// <returns>A stairstep starting filled on the bottom row, pointing in the maximum x or z direction</returns>
        private IEnumerable <GlobalVoxelCoordinate> EnumerateStairVoxels(BoundingBox box, Vector3 start, Vector3 end, bool invert)
        {
            // Todo: Can this be simplified to return voxels above or below the line?
            int minX = MathFunctions.FloorInt(box.Min.X + 0.5f);
            int minY = MathFunctions.FloorInt(box.Min.Y + 0.5f);
            int minZ = MathFunctions.FloorInt(box.Min.Z + 0.5f);
            int maxX = MathFunctions.FloorInt(box.Max.X - 0.5f);
            int maxY = MathFunctions.FloorInt(box.Max.Y - 0.5f);
            int maxZ = MathFunctions.FloorInt(box.Max.Z - 0.5f);

            // If not inverted, selects the Xs
            // If inverted, selects the Os
            //max y ----xOOOO
            //      --- xxOOO
            //      --- xxxOO
            //      --- xxxxO
            //min y --- xxxxx
            //        minx --- maxx
            float   dx          = box.Max.X - box.Min.X;
            float   dz          = box.Max.Z - box.Min.Z;
            Vector3 dir         = end - start;
            bool    direction   = dx > dz;
            bool    positiveDir = direction ? dir.X < 0 : dir.Z < 0;
            int     step        = 0;

            // Always make staircases go exactly to the top or bottom of the selection.
            if (direction && invert)
            {
                minY = maxY - (maxX - minX);
            }
            else if (direction)
            {
                maxY = minY + (maxX - minX);
            }
            else if (invert)
            {
                minY = maxY - (maxZ - minZ);
            }
            else
            {
                maxY = minY + (maxZ - minZ);
            }
            int dy = maxY - minY;

            // Start from the bottom of the stairs up to the top.
            for (int y = minY; y <= maxY; y++)
            {
                int carve = invert ? MathFunctions.Clamp(dy - step, 0, dy) : step;
                // If stairs are in x direction
                if (direction)
                {
                    if (positiveDir)
                    {
                        // Start from min x, and march up to maxY - y
                        for (int x = minX; x <= MathFunctions.Clamp(maxX - carve, minX, maxX); x++)
                        {
                            for (int z = minZ; z <= maxZ; z++)
                            {
                                yield return(new GlobalVoxelCoordinate(x, y, z));
                            }
                        }
                    }
                    else
                    {
                        // Start from min x, and march up to maxY - y
                        for (int x = maxX; x >= MathFunctions.Clamp(minX + carve, minX, maxX); x--)
                        {
                            for (int z = minZ; z <= maxZ; z++)
                            {
                                yield return(new GlobalVoxelCoordinate(x, y, z));
                            }
                        }
                    }
                    step++;
                }
                // Otherwise, they are in the z direction.
                else
                {
                    if (positiveDir)
                    {
                        // Start from min z, and march up to maxY - y
                        for (int z = minZ; z <= MathFunctions.Clamp(maxZ - carve, minZ, maxZ); z++)
                        {
                            for (int x = minX; x <= maxX; x++)
                            {
                                yield return(new GlobalVoxelCoordinate(x, y, z));
                            }
                        }
                    }
                    else
                    {
                        // Start from min z, and march up to maxY - y
                        for (int z = maxZ; z >= MathFunctions.Clamp(minZ + carve, minZ, maxZ); z--)
                        {
                            for (int x = minX; x <= maxX; x++)
                            {
                                yield return(new GlobalVoxelCoordinate(x, y, z));
                            }
                        }
                    }
                    step++;
                }
            }
        }
예제 #9
0
 public List <T> GetItems(Voxel voxel)
 {
     return(GetItems(new Point3(MathFunctions.FloorInt(voxel.Position.X),
                                MathFunctions.FloorInt(voxel.Position.Y),
                                MathFunctions.FloorInt(voxel.Position.Z))));
 }
예제 #10
0
 public List <IBoundedObject> GetObjectsAt(Voxel voxel, CollisionType queryType)
 {
     return(GetObjectsAt(new Point3(MathFunctions.FloorInt(voxel.Position.X),
                                    MathFunctions.FloorInt(voxel.Position.Y), MathFunctions.FloorInt(voxel.Position.Z)), queryType));
 }
예제 #11
0
        public List <Creature.MoveAction> GetMoveActions(Voxel voxel)
        {
            List <Creature.MoveAction> toReturn = new List <Creature.MoveAction>();

            CollisionManager objectHash = PlayState.ComponentManager.CollisionManager;

            Voxel[,,] neighborHood = GetNeighborhood(voxel);
            int  x                = (int)voxel.GridPosition.X;
            int  y                = (int)voxel.GridPosition.Y;
            int  z                = (int)voxel.GridPosition.Z;
            bool inWater          = (neighborHood[1, 1, 1] != null && neighborHood[1, 1, 1].WaterLevel > 5);
            bool standingOnGround = (neighborHood[1, 0, 1] != null && !neighborHood[1, 0, 1].IsEmpty);
            bool topCovered       = (neighborHood[1, 2, 1] != null && !neighborHood[1, 2, 1].IsEmpty);
            bool hasNeighbors     = HasNeighbors(neighborHood);


            List <Creature.MoveAction> successors = new List <Creature.MoveAction>();

            //Climbing ladders
            List <IBoundedObject> bodiesInside =
                objectHash.Hashes[CollisionManager.CollisionType.Static].GetItems(
                    new Point3(MathFunctions.FloorInt(voxel.Position.X),
                               MathFunctions.FloorInt(voxel.Position.Y),
                               MathFunctions.FloorInt(voxel.Position.Z)));

            if (bodiesInside != null)
            {
                bool hasLadder =
                    bodiesInside.OfType <GameComponent>()
                    .Any(component => component.Tags.Contains("Climbable"));
                if (hasLadder)
                {
                    ;
                }
                {
                    successors.Add(new Creature.MoveAction()
                    {
                        Diff     = new Vector3(1, 2, 1),
                        MoveType = Creature.MoveType.Climb
                    });

                    if (!standingOnGround)
                    {
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff     = new Vector3(1, 0, 1),
                            MoveType = Creature.MoveType.Climb
                        });
                    }

                    standingOnGround = true;
                }
            }


            if (standingOnGround || inWater)
            {
                Creature.MoveType moveType = inWater ? Creature.MoveType.Swim : Creature.MoveType.Walk;
                if (IsEmpty(neighborHood[0, 1, 1]))
                {
                    // +- x
                    successors.Add(new Creature.MoveAction()
                    {
                        Diff     = new Vector3(0, 1, 1),
                        MoveType = moveType
                    });
                }

                if (IsEmpty(neighborHood[2, 1, 1]))
                {
                    successors.Add(new Creature.MoveAction()
                    {
                        Diff     = new Vector3(2, 1, 1),
                        MoveType = moveType
                    });
                }

                if (IsEmpty(neighborHood[1, 1, 0]))
                {
                    // +- z
                    successors.Add(new Creature.MoveAction()
                    {
                        Diff     = new Vector3(1, 1, 0),
                        MoveType = moveType
                    });
                }

                if (IsEmpty(neighborHood[1, 1, 2]))
                {
                    successors.Add(new Creature.MoveAction()
                    {
                        Diff     = new Vector3(1, 1, 2),
                        MoveType = moveType
                    });
                }

                if (!hasNeighbors)
                {
                    if (IsEmpty(neighborHood[2, 1, 2]))
                    {
                        // +x + z
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff     = new Vector3(2, 1, 2),
                            MoveType = moveType
                        });
                    }

                    if (IsEmpty(neighborHood[2, 1, 0]))
                    {
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff     = new Vector3(2, 1, 0),
                            MoveType = moveType
                        });
                    }

                    if (IsEmpty(neighborHood[0, 1, 2]))
                    {
                        // -x -z
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff     = new Vector3(0, 1, 2),
                            MoveType = moveType
                        });
                    }

                    if (IsEmpty(neighborHood[0, 1, 0]))
                    {
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff     = new Vector3(0, 1, 0),
                            MoveType = moveType
                        });
                    }
                }
            }

            if (!topCovered && (standingOnGround || inWater))
            {
                for (int dx = 0; dx <= 2; dx++)
                {
                    for (int dz = 0; dz <= 2; dz++)
                    {
                        if (dx == 1 && dz == 1)
                        {
                            continue;
                        }

                        if (!IsEmpty(neighborHood[dx, 1, dz]))
                        {
                            successors.Add(new Creature.MoveAction()
                            {
                                Diff     = new Vector3(dx, 2, dz),
                                MoveType = Creature.MoveType.Jump
                            });
                        }
                    }
                }
            }


            // Falling
            if (!inWater && !standingOnGround)
            {
                successors.Add(new Creature.MoveAction()
                {
                    Diff     = new Vector3(1, 0, 1),
                    MoveType = Creature.MoveType.Fall
                });
            }


            foreach (Creature.MoveAction v in successors)
            {
                Voxel n = neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z];
                if (n != null && (n.IsEmpty || n.WaterLevel > 0))
                {
                    Creature.MoveAction newAction = v;
                    newAction.Voxel = n;
                    toReturn.Add(newAction);
                }
            }


            return(toReturn);
        }
예제 #12
0
 public Point3(Vector3 vect)
 {
     X = MathFunctions.FloorInt(vect.X);
     Y = MathFunctions.FloorInt(vect.Y);
     Z = MathFunctions.FloorInt(vect.Z);
 }
예제 #13
0
 public Point3 GetChunkID(Vector3 origin)
 {
     origin = RoundToChunkCoords(origin);
     return(new Point3(MathFunctions.FloorInt(origin.X), MathFunctions.FloorInt(origin.Y), MathFunctions.FloorInt(origin.Z)));
 }
예제 #14
0
        public List<Creature.MoveAction> GetMoveActions(Voxel voxel)
        {
            List<Creature.MoveAction> toReturn = new List<Creature.MoveAction>();
           
            CollisionManager objectHash = PlayState.ComponentManager.CollisionManager;

            Voxel[,,] neighborHood = GetNeighborhood(voxel);
            int x = (int)voxel.GridPosition.X;
            int y = (int)voxel.GridPosition.Y;
            int z = (int)voxel.GridPosition.Z;
            bool inWater = (neighborHood[1, 1, 1] != null && neighborHood[1, 1, 1].WaterLevel > 5);
            bool standingOnGround = (neighborHood[1, 0, 1] != null && !neighborHood[1, 0, 1].IsEmpty);
            bool topCovered = (neighborHood[1, 2, 1] != null && !neighborHood[1, 2, 1].IsEmpty);
            bool hasNeighbors = HasNeighbors(neighborHood);


            List<Creature.MoveAction> successors = new List<Creature.MoveAction>();

            //Climbing ladders
            IEnumerable<IBoundedObject> objectsInside =
                objectHash.Hashes[CollisionManager.CollisionType.Static].GetItems(
                    new Point3(MathFunctions.FloorInt(voxel.Position.X),
                        MathFunctions.FloorInt(voxel.Position.Y),
                        MathFunctions.FloorInt(voxel.Position.Z)));

            bool blockedByObject = false;
            if (objectsInside != null)
            {
                var bodies = objectsInside.OfType<GameComponent>();
                var enumerable = bodies as IList<GameComponent> ?? bodies.ToList();
                // TODO: This is supposed to be done when the door is a NEIGHBOR of this voxel only!!
                foreach (GameComponent body in enumerable)
                {
                    Door door = body.GetRootComponent().GetChildrenOfType<Door>(true).FirstOrDefault();

                    if (door != null)
                    {
                        if (
                            PlayState.Diplomacy.GetPolitics(door.TeamFaction, Creature.Faction).GetCurrentRelationship() ==
                            Relationship.Hateful)
                        {

                            if (IsEmpty(neighborHood[0, 1, 1]))
                                // +- x
                                successors.Add(new Creature.MoveAction()
                                {
                                    Diff = new Vector3(0, 1, 1),
                                    MoveType = Creature.MoveType.DestroyObject,
                                    InteractObject = door,
                                    Voxel = neighborHood[0, 1, 1]
                                });

                            if (IsEmpty(neighborHood[2, 1, 1]))
                                successors.Add(new Creature.MoveAction()
                                {
                                    Diff = new Vector3(2, 1, 1),
                                    MoveType = Creature.MoveType.DestroyObject,
                                    InteractObject = door,
                                    Voxel = neighborHood[2, 1, 1]
                                });

                            if (IsEmpty(neighborHood[1, 1, 0]))
                                // +- z
                                successors.Add(new Creature.MoveAction()
                                {
                                    Diff = new Vector3(1, 1, 0),
                                    MoveType = Creature.MoveType.DestroyObject,
                                    InteractObject = door,
                                    Voxel = neighborHood[1, 1, 0]
                                });

                            if (IsEmpty(neighborHood[1, 1, 2]))
                                successors.Add(new Creature.MoveAction()
                                {
                                    Diff = new Vector3(1, 1, 2),
                                    MoveType = Creature.MoveType.DestroyObject,
                                    InteractObject = door,
                                    Voxel = neighborHood[1, 1, 2]
                                });


                            blockedByObject = true;
                        }
                    }
                }

                if (blockedByObject)
                {
                    return successors;
                }

                if (CanClimb)
                {
                    bool hasLadder = enumerable.Any(component => component.Tags.Contains("Climbable"));
                    if (hasLadder)
                    {
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff = new Vector3(1, 2, 1),
                            MoveType = Creature.MoveType.Climb
                        });

                        if (!standingOnGround)
                        {
                            successors.Add(new Creature.MoveAction()
                            {
                                Diff = new Vector3(1, 0, 1),
                                MoveType = Creature.MoveType.Climb
                            });
                        }

                        standingOnGround = true;
                    }
                }
            }


            if (standingOnGround || (CanSwim && inWater))
            {
                Creature.MoveType moveType = inWater ? Creature.MoveType.Swim : Creature.MoveType.Walk;
                if (IsEmpty(neighborHood[0, 1, 1]))
                    // +- x
                    successors.Add(new Creature.MoveAction()
                    {
                        Diff = new Vector3(0, 1, 1),
                        MoveType = moveType
                    });

                if (IsEmpty(neighborHood[2, 1, 1]))
                    successors.Add(new Creature.MoveAction()
                    {
                        Diff = new Vector3(2, 1, 1),
                        MoveType = moveType
                    });

                if (IsEmpty(neighborHood[1, 1, 0]))
                    // +- z
                    successors.Add(new Creature.MoveAction()
                    {
                        Diff = new Vector3(1, 1, 0),
                        MoveType = moveType
                    });

                if (IsEmpty(neighborHood[1, 1, 2]))
                    successors.Add(new Creature.MoveAction()
                    {
                        Diff = new Vector3(1, 1, 2),
                        MoveType = moveType
                    });

                if (!hasNeighbors)
                {
                    if (IsEmpty(neighborHood[2, 1, 2]))
                        // +x + z
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff = new Vector3(2, 1, 2),
                            MoveType = moveType
                        });

                    if (IsEmpty(neighborHood[2, 1, 0]))
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff = new Vector3(2, 1, 0),
                            MoveType = moveType
                        });

                    if (IsEmpty(neighborHood[0, 1, 2]))
                        // -x -z
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff = new Vector3(0, 1, 2),
                            MoveType = moveType
                        });

                    if (IsEmpty(neighborHood[0, 1, 0]))
                        successors.Add(new Creature.MoveAction()
                        {
                            Diff = new Vector3(0, 1, 0),
                            MoveType = moveType
                        });
                }

            }

            if (!topCovered && (standingOnGround || (CanSwim && inWater)))
            {
                for (int dx = 0; dx <= 2; dx++)
                {
                    for (int dz = 0; dz <= 2; dz++)
                    {
                        if (dx == 1 && dz == 1) continue;

                        if (!IsEmpty(neighborHood[dx, 1, dz]))
                        {
                            successors.Add(new Creature.MoveAction()
                            {
                                Diff = new Vector3(dx, 2, dz),
                                MoveType = Creature.MoveType.Jump
                            });
                        }
                    }
                }

            }


            // Falling
            if (!inWater && !standingOnGround)
            {
                successors.Add(new Creature.MoveAction()
                {
                    Diff = new Vector3(1, 0, 1),
                    MoveType = Creature.MoveType.Fall
                });
            }

            if (CanFly)
            {
                for (int dx = 0; dx <= 2; dx++)
                {
                    for (int dz = 0; dz <= 2; dz++)
                    {
                        for (int dy = 0; dy <= 2; dy++)
                        {
                            if (dx == 1 && dz == 1 && dy == 1) continue;

                            if (IsEmpty(neighborHood[dx, 1, dz]))
                            {
                                successors.Add(new Creature.MoveAction()
                                {
                                    Diff = new Vector3(dx, dy, dz),
                                    MoveType = Creature.MoveType.Fly
                                });
                            }
                        }
                    }
                }
            }


            foreach (Creature.MoveAction v in successors)
            {
                Voxel n = neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z];
                if (n != null && (n.IsEmpty || n.WaterLevel > 0))
                {
                    Creature.MoveAction newAction = v;
                    newAction.Voxel = n;
                    toReturn.Add(newAction);
                }
            }


            return toReturn;
        }