private void LoadThreaded()
        {
            // Ensure we're using the invariant culture.
            Thread.CurrentThread.CurrentCulture   = CultureInfo.InvariantCulture;
            Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
            LoadStatus = LoadingStatus.Loading;
            SetLoadingMessage("Initializing ...");

            while (GraphicsDevice == null)
            {
                Thread.Sleep(100);
            }
            Thread.Sleep(1000);

#if CREATE_CRASH_LOGS
            try
#endif
#if !DEBUG
            try
            {
#endif
            bool fileExists = !string.IsNullOrEmpty(ExistingFile);

            SetLoadingMessage("Creating Sky...");

            Sky = new SkyRenderer(
                TextureManager.GetTexture(ContentPaths.Sky.moon),
                TextureManager.GetTexture(ContentPaths.Sky.sun),
                Content.Load <TextureCube>(ContentPaths.Sky.day_sky),
                Content.Load <TextureCube>(ContentPaths.Sky.night_sky),
                TextureManager.GetTexture(ContentPaths.Gradients.skygradient),
                Content.Load <Model>(ContentPaths.Models.sphereLowPoly),
                Content.Load <Effect>(ContentPaths.Shaders.SkySphere),
                Content.Load <Effect>(ContentPaths.Shaders.Background));

            #region Reading game file

            if (fileExists)
            {
                SetLoadingMessage("Loading " + ExistingFile);

                gameFile = SaveGame.CreateFromDirectory(ExistingFile);
                if (gameFile == null)
                {
                    throw new InvalidOperationException("Game File does not exist.");
                }

                // Todo: REMOVE THIS WHEN THE NEW SAVE SYSTEM IS COMPLETE.
                if (gameFile.Metadata.Version != Program.Version && !Program.CompatibleVersions.Contains(gameFile.Metadata.Version))
                {
                    throw new InvalidOperationException(String.Format("Game file is from version {0}. Compatible versions are {1}.", gameFile.Metadata.Version,
                                                                      TextGenerator.GetListString(Program.CompatibleVersions)));
                }
                Sky.TimeOfDay = gameFile.Metadata.TimeOfDay;
                Time          = gameFile.Metadata.Time;
                WorldOrigin   = gameFile.Metadata.WorldOrigin;
                WorldScale    = gameFile.Metadata.WorldScale;
                WorldSize     = gameFile.Metadata.NumChunks;
                GameID        = gameFile.Metadata.GameID;

                if (gameFile.Metadata.OverworldFile != null && gameFile.Metadata.OverworldFile != "flat")
                {
                    SetLoadingMessage("Loading world " + gameFile.Metadata.OverworldFile);
                    Overworld.Name = gameFile.Metadata.OverworldFile;
                    DirectoryInfo worldDirectory =
                        Directory.CreateDirectory(DwarfGame.GetWorldDirectory() +
                                                  ProgramData.DirChar + Overworld.Name);
                    var overWorldFile = new NewOverworldFile(worldDirectory.FullName);
                    Overworld.Map  = overWorldFile.Data.Data;
                    Overworld.Name = overWorldFile.Data.Name;
                }
                else
                {
                    SetLoadingMessage("Generating flat world..");
                    Overworld.CreateUniformLand(GraphicsDevice);
                }
            }

            #endregion

            #region Initialize static data

            {
                Vector3 origin  = new Vector3(WorldOrigin.X, 0, WorldOrigin.Y);
                Vector3 extents = new Vector3(1500, 1500, 1500);
                CollisionManager = new CollisionManager(new BoundingBox(origin - extents, origin + extents));

                CraftLibrary = new CraftLibrary();

                new PrimitiveLibrary(GraphicsDevice, Content);
                NewInstanceManager = new NewInstanceManager(GraphicsDevice, new BoundingBox(origin - extents, origin + extents),
                                                            Content);

                Color[] white = new Color[1];
                white[0] = Color.White;
                pixel    = new Texture2D(GraphicsDevice, 1, 1);
                pixel.SetData(white);

                Tilesheet                  = TextureManager.GetTexture(ContentPaths.Terrain.terrain_tiles);
                AspectRatio                = GraphicsDevice.Viewport.AspectRatio;
                DefaultShader              = new Shader(Content.Load <Effect>(ContentPaths.Shaders.TexturedShaders), true);
                DefaultShader.ScreenWidth  = GraphicsDevice.Viewport.Width;
                DefaultShader.ScreenHeight = GraphicsDevice.Viewport.Height;
                VoxelLibrary.InitializeDefaultLibrary(GraphicsDevice, Tilesheet);
                GrassLibrary.InitializeDefaultLibrary();
                DecalLibrary.InitializeDefaultLibrary();

                bloom = new BloomComponent(Game)
                {
                    Settings = BloomSettings.PresetSettings[5]
                };
                bloom.Initialize();


                fxaa = new FXAA();
                fxaa.Initialize();

                SoundManager.Content = Content;
                if (PlanService != null)
                {
                    PlanService.Restart();
                }

                JobLibrary.Initialize();
                MonsterSpawner = new MonsterSpawner(this);
                EntityFactory.Initialize(this);
            }

            #endregion


            SetLoadingMessage("Creating Planner ...");
            PlanService = new PlanService();

            SetLoadingMessage("Creating Shadows...");
            Shadows = new ShadowRenderer(GraphicsDevice, 1024, 1024);

            SetLoadingMessage("Creating Liquids ...");

            #region liquids

            WaterRenderer = new WaterRenderer(GraphicsDevice);

            LiquidAsset waterAsset = new LiquidAsset
            {
                Type        = LiquidType.Water,
                Opactiy     = 0.8f,
                Reflection  = 1.0f,
                WaveHeight  = 0.1f,
                WaveLength  = 0.05f,
                WindForce   = 0.001f,
                BumpTexture = TextureManager.GetTexture(ContentPaths.Terrain.water_normal),
                BaseTexture = TextureManager.GetTexture(ContentPaths.Terrain.cartoon_water),
                MinOpacity  = 0.4f,
                RippleColor = new Vector4(0.6f, 0.6f, 0.6f, 0.0f),
                FlatColor   = new Vector4(0.3f, 0.3f, 0.9f, 1.0f)
            };
            WaterRenderer.AddLiquidAsset(waterAsset);


            LiquidAsset lavaAsset = new LiquidAsset
            {
                Type        = LiquidType.Lava,
                Opactiy     = 0.95f,
                Reflection  = 0.0f,
                WaveHeight  = 0.1f,
                WaveLength  = 0.05f,
                WindForce   = 0.001f,
                MinOpacity  = 0.8f,
                BumpTexture = TextureManager.GetTexture(ContentPaths.Terrain.water_normal),
                BaseTexture = TextureManager.GetTexture(ContentPaths.Terrain.lava),
                RippleColor = new Vector4(0.5f, 0.4f, 0.04f, 0.0f),
                FlatColor   = new Vector4(0.9f, 0.7f, 0.2f, 1.0f)
            };

            WaterRenderer.AddLiquidAsset(lavaAsset);

            #endregion

            SetLoadingMessage("Generating Initial Terrain Chunks ...");

            if (!fileExists)
            {
                GameID = MathFunctions.Random.Next(0, 1024);
            }

            ChunkGenerator = new ChunkGenerator(VoxelLibrary, Seed, 0.02f, this.WorldScale)
            {
                SeaLevel = SeaLevel
            };


            #region Load Components

            if (fileExists)
            {
                ChunkManager = new ChunkManager(Content, this, Camera,
                                                GraphicsDevice,
                                                ChunkGenerator, WorldSize.X, WorldSize.Y, WorldSize.Z);

                ChunkRenderer = new ChunkRenderer(this, Camera, GraphicsDevice, ChunkManager.ChunkData);

                SetLoadingMessage("Loading Terrain...");
                gameFile.ReadChunks(ExistingFile);
                ChunkManager.ChunkData.LoadFromFile(gameFile, SetLoadingMessage);

                ChunkManager.ChunkData.SetMaxViewingLevel(gameFile.Metadata.Slice > 0
                        ? gameFile.Metadata.Slice
                        : ChunkManager.ChunkData.MaxViewingLevel, ChunkManager.SliceMode.Y);

                SetLoadingMessage("Loading Entities...");
                gameFile.LoadPlayData(ExistingFile, this);
                Camera = gameFile.PlayData.Camera;
                ChunkManager.camera  = Camera;
                ChunkRenderer.camera = Camera;
                DesignationDrawer    = gameFile.PlayData.Designations;

                Vector3 origin  = new Vector3(WorldOrigin.X, 0, WorldOrigin.Y);
                Vector3 extents = new Vector3(1500, 1500, 1500);
                CollisionManager = new CollisionManager(new BoundingBox(origin - extents, origin + extents));

                if (gameFile.PlayData.Resources != null)
                {
                    foreach (var resource in gameFile.PlayData.Resources)
                    {
                        if (!ResourceLibrary.Resources.ContainsKey(resource.Key))
                        {
                            ResourceLibrary.Add(resource.Value);
                        }
                    }
                }
                ComponentManager = new ComponentManager(gameFile.PlayData.Components, this);

                foreach (var component in gameFile.PlayData.Components.SaveableComponents)
                {
                    if (!ComponentManager.HasComponent(component.GlobalID) &&
                        ComponentManager.HasComponent(component.Parent.GlobalID))
                    {
                        // Logically impossible.
                        throw new InvalidOperationException("Component exists in save data but not in manager.");
                    }
                }

                Factions = gameFile.PlayData.Factions;
                ComponentManager.World = this;

                Sky.TimeOfDay = gameFile.Metadata.TimeOfDay;
                Time          = gameFile.Metadata.Time;
                WorldOrigin   = gameFile.Metadata.WorldOrigin;
                WorldScale    = gameFile.Metadata.WorldScale;

                // Restore native factions from deserialized data.
                Natives = new List <Faction>();
                foreach (Faction faction in Factions.Factions.Values)
                {
                    if (faction.Race.IsNative && faction.Race.IsIntelligent && !faction.IsRaceFaction)
                    {
                        Natives.Add(faction);
                    }
                }

                Diplomacy = gameFile.PlayData.Diplomacy;

                GoalManager = new Goals.GoalManager();
                GoalManager.Initialize(gameFile.PlayData.Goals);

                TutorialManager = new Tutorial.TutorialManager(Program.CreatePath("Content", "tutorial.txt"));
                TutorialManager.SetFromSaveData(gameFile.PlayData.TutorialSaveData);
            }
            else
            {
                Time = new WorldTime();
                // WorldOrigin is in "map" units. Convert to voxels
                var globalOffset = new Vector3(WorldOrigin.X, 0, WorldOrigin.Y) * WorldScale;

                Camera = new OrbitCamera(this,
                                         new Vector3(VoxelConstants.ChunkSizeX,
                                                     VoxelConstants.ChunkSizeY - 1.0f,
                                                     VoxelConstants.ChunkSizeZ) + new Vector3(WorldOrigin.X, 0, WorldOrigin.Y) * WorldScale,
                                         new Vector3(VoxelConstants.ChunkSizeY, VoxelConstants.ChunkSizeY - 1.0f,
                                                     VoxelConstants.ChunkSizeZ) + new Vector3(WorldOrigin.X, 0, WorldOrigin.Y) * WorldScale +
                                         Vector3.Up * 10.0f + Vector3.Backward * 10,
                                         MathHelper.PiOver4, AspectRatio, 0.1f,
                                         GameSettings.Default.VertexCullDistance);

                ChunkManager = new ChunkManager(Content, this, Camera,
                                                GraphicsDevice,
                                                ChunkGenerator, WorldSize.X, WorldSize.Y, WorldSize.Z);

                ChunkRenderer = new ChunkRenderer(this, Camera, GraphicsDevice, ChunkManager.ChunkData);


                var chunkOffset = GlobalVoxelCoordinate.FromVector3(globalOffset).GetGlobalChunkCoordinate();
                //var chunkOffset = ChunkManager.ChunkData.RoundToChunkCoords(globalOffset);
                //globalOffset.X = chunkOffset.X * VoxelConstants.ChunkSizeX;
                //globalOffset.Y = chunkOffset.Y * VoxelConstants.ChunkSizeY;
                //globalOffset.Z = chunkOffset.Z * VoxelConstants.ChunkSizeZ;

                WorldOrigin     = new Vector2(globalOffset.X, globalOffset.Z);
                Camera.Position = new Vector3(0, 10, 0) + globalOffset;
                Camera.Target   = new Vector3(0, 10, 1) + globalOffset;

                // If there's no file, we have to initialize the first chunk coordinate
                if (gameFile == null)     // Todo: Always true?
                {
                    ChunkManager.GenerateInitialChunks(
                        GlobalVoxelCoordinate.FromVector3(globalOffset).GetGlobalChunkCoordinate(),
                        SetLoadingMessage);
                }

                ComponentManager = new ComponentManager(this);
                ComponentManager.SetRootComponent(new Body(ComponentManager, "root", Matrix.Identity,
                                                           Vector3.Zero, Vector3.Zero, false));

                if (Natives == null)     // Todo: Always true??
                {
                    FactionLibrary library = new FactionLibrary();
                    library.Initialize(this, CompanyMakerState.CompanyInformation);
                    Natives = new List <Faction>();
                    for (int i = 0; i < 10; i++)
                    {
                        Natives.Add(library.GenerateFaction(this, i, 10));
                    }
                }

                #region Prepare Factions

                foreach (Faction faction in Natives)
                {
                    faction.World = this;

                    if (faction.RoomBuilder == null)
                    {
                        faction.RoomBuilder = new RoomBuilder(faction, this);
                    }

                    if (faction.CraftBuilder == null)
                    {
                        faction.CraftBuilder = new CraftBuilder(faction, this);
                    }
                }

                Factions = new FactionLibrary();
                if (Natives != null && Natives.Count > 0)
                {
                    Factions.AddFactions(this, Natives);
                }

                Factions.Initialize(this, CompanyMakerState.CompanyInformation);
                Point playerOrigin = new Point((int)(WorldOrigin.X), (int)(WorldOrigin.Y));

                Factions.Factions["Player"].Center         = playerOrigin;
                Factions.Factions["The Motherland"].Center = new Point(playerOrigin.X + 50, playerOrigin.Y + 50);

                #endregion

                Diplomacy = new Diplomacy(this);
                Diplomacy.Initialize(Time.CurrentDate);

                // Initialize goal manager here.
                GoalManager = new Goals.GoalManager();
                GoalManager.Initialize(new List <Goals.Goal>());

                TutorialManager = new Tutorial.TutorialManager(Program.CreatePath("Content", "tutorial.txt"));
                TutorialManager.TutorialEnabled = !GameSettings.Default.TutorialDisabledGlobally;
                Tutorial("new game start");
            }

            Camera.World = this;
            //Drawer3D.Camera = Camera;


            #endregion

            ChunkManager.camera = Camera;

            SetLoadingMessage("Creating Particles ...");
            ParticleManager = new ParticleManager(GraphicsDevice, ComponentManager);

            SetLoadingMessage("Creating GameMaster ...");
            Master = new GameMaster(Factions.Factions["Player"], Game, ComponentManager, ChunkManager,
                                    Camera, GraphicsDevice);

            if (gameFile != null)
            {
                if (gameFile.PlayData.Spells != null)
                {
                    Master.Spells = gameFile.PlayData.Spells;
                }
                if (gameFile.PlayData.Tasks != null)
                {
                    Master.TaskManager = gameFile.PlayData.Tasks;
                }
            }

            if (Master.Faction.Economy.Company.Information == null)
            {
                Master.Faction.Economy.Company.Information = new CompanyInformation();
            }

            CreateInitialEmbarkment();
            foreach (var chunk in ChunkManager.ChunkData.ChunkMap)
            {
                chunk.CalculateInitialSunlight();
            }
            VoxelHelpers.InitialReveal(ChunkManager.ChunkData, new VoxelHandle(
                                           ChunkManager.ChunkData.GetChunkEnumerator().FirstOrDefault(), new LocalVoxelCoordinate(0, VoxelConstants.ChunkSizeY - 1, 0)));

            foreach (var chunk in ChunkManager.ChunkData.ChunkMap)
            {
                ChunkManager.InvalidateChunk(chunk);
            }

            ChunkManager.StartThreads();
            SetLoadingMessage("Presimulating ...");
            ShowingWorld = false;
            OnLoadedEvent();

            Thread.Sleep(1000);
            ShowingWorld = true;

            SetLoadingMessage("Complete.");

            // GameFile is no longer needed.
            gameFile   = null;
            LoadStatus = LoadingStatus.Success;
#if !DEBUG
        }

        catch (Exception exception)
        {
            Game.CaptureException(exception);
            LoadingException = exception;
            LoadStatus       = LoadingStatus.Failure;
        }
#endif
        }
Exemple #2
0
        public List <Body> FrustrumCullLocatableComponents(Camera camera)
        {
            List <Body> visible = CollisionManager.GetVisibleObjects <Body>(camera.GetFrustrum(), CollisionManager.CollisionType.Dynamic | CollisionManager.CollisionType.Static);

            return(visible);
        }
        public IEnumerable <MoveAction> GetInverseMoveActions_Experimental(VoxelHandle voxel)
        {
            if (!voxel.IsValid || !voxel.IsEmpty)
            {
                yield break;
            }

            CollisionManager objectHash = Creature.Manager.World.CollisionManager;

            var  neighborHood     = GetNeighborhood(voxel);
            bool inWater          = (neighborHood[1, 1, 1].IsValid && neighborHood[1, 1, 1].WaterCell.WaterLevel > WaterManager.inWaterThreshold);
            bool standingOnGround = (neighborHood[1, 0, 1].IsValid && !neighborHood[1, 0, 1].IsEmpty);
            bool topCovered       = (neighborHood[1, 2, 1].IsValid && !neighborHood[1, 2, 1].IsEmpty);
            bool hasNeighbors     = HasNeighbors(neighborHood);
            bool isClimbing       = false;

            var successors = new List <MoveAction>();

            if (CanClimb)
            {
                var ladderAt    = GetBodyAt(voxel, objectHash, "Climbable");
                var ladderAbove = GetBodyAt(VoxelHelpers.GetVoxelAbove(voxel), objectHash, "Climbable");
                var ladderBelow = GetBodyAt(VoxelHelpers.GetNeighbor(voxel, new GlobalVoxelOffset(0, -1, 0)), objectHash, "Climbable");
                // If there was a ladder above the creature, we could have climbed down it to get here.
                if (ladderAbove != null)
                {
                    successors.Add(new MoveAction
                    {
                        Diff           = new Vector3(1, 2, 1),
                        MoveType       = MoveType.Climb,
                        InteractObject = ladderAbove
                    });
                }

                // If there was a ladder below the creature, we could have climbed up to get here.
                if (ladderBelow != null)
                {
                    successors.Add(new MoveAction
                    {
                        Diff           = new Vector3(1, 0, 1),
                        MoveType       = MoveType.Climb,
                        InteractObject = ladderBelow
                    });
                }

                if (ladderAt != null)
                {
                    standingOnGround = true;
                    isClimbing       = true;
                }
            }

            // If the creature can climb walls, check to see if there are any walls nearby that we could have climbed here from.
            if (CanClimbWalls && !topCovered)
            {
                // First check the voxel above to see if it has any walls nearby.
                if (!topCovered)
                {
                    var wallsAbove = new VoxelHandle[]
                    {
                        neighborHood[2, 2, 1], neighborHood[0, 2, 1], neighborHood[1, 2, 2],
                        neighborHood[1, 2, 0]
                    };
                    var wallAbove = VoxelHandle.InvalidHandle;
                    foreach (var w in wallsAbove)
                    {
                        if (w.IsValid && !w.IsEmpty)
                        {
                            wallAbove = w;
                            break;
                        }
                    }


                    // If there was a wall above us, we could have climbed down to get here.
                    if (wallAbove.IsValid)
                    {
                        successors.Add(new MoveAction
                        {
                            Diff        = new Vector3(1, 2, 1),
                            MoveType    = MoveType.ClimbWalls,
                            ActionVoxel = wallAbove
                        });
                    }
                }

                // Now check the walls below
                if (!standingOnGround)
                {
                    var wallsBelow = new VoxelHandle[]
                    {
                        neighborHood[2, 0, 1], neighborHood[0, 0, 1], neighborHood[1, 0, 2],
                        neighborHood[1, 0, 0]
                    };
                    var wallBelow = VoxelHandle.InvalidHandle;
                    foreach (var w in wallsBelow)
                    {
                        if (w.IsValid && !w.IsEmpty)
                        {
                            wallBelow = w;
                            break;
                        }
                    }


                    // If there was a wall below us, we could have climbed up to get here.
                    if (wallBelow.IsValid)
                    {
                        successors.Add(new MoveAction
                        {
                            Diff        = new Vector3(1, 0, 1),
                            MoveType    = MoveType.ClimbWalls,
                            ActionVoxel = wallBelow
                        });
                    }
                }
            }

            // If the creature either can walk or is in water, add the
            // eight-connected free neighbors around the voxel.
            if (CanWalk || CanSwim)
            {
                // If the creature is in water, it can swim. Otherwise, it will walk.
                var moveType = inWater ? MoveType.Swim : MoveType.Walk;
                if (neighborHood[0, 1, 1].IsValid &&
                    neighborHood[0, 1, 1].IsEmpty)
                {
                    if (moveType == MoveType.Swim || (neighborHood[0, 0, 1].IsValid &&
                                                      !neighborHood[0, 0, 1].IsEmpty))
                    {
                        successors.Add(new MoveAction
                        {
                            Diff     = new Vector3(0, 1, 1),
                            MoveType = moveType
                        });
                    }
                }

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


                if (neighborHood[1, 1, 0].IsValid && neighborHood[1, 1, 0].IsEmpty)
                {
                    if (moveType == MoveType.Swim || (neighborHood[1, 0, 0].IsValid &&
                                                      !neighborHood[1, 0, 0].IsEmpty))
                    {
                        successors.Add(new MoveAction
                        {
                            Diff     = new Vector3(1, 1, 0),
                            MoveType = moveType
                        });
                    }
                }

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

                // Only bother worrying about 8-connected movement if there are
                // no full neighbors around the voxel.
                if (!hasNeighbors)
                {
                    if (neighborHood[2, 1, 2].IsValid && neighborHood[2, 1, 2].IsEmpty)
                    {
                        if (moveType == MoveType.Swim || (neighborHood[2, 0, 2].IsValid &&
                                                          !neighborHood[2, 0, 2].IsEmpty))
                        {
                            successors.Add(new MoveAction
                            {
                                Diff     = new Vector3(2, 1, 2),
                                MoveType = moveType
                            });
                        }
                    }

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

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

                    if (neighborHood[0, 1, 0].IsValid && neighborHood[0, 1, 0].IsEmpty)
                    {
                        if (moveType == MoveType.Swim || (neighborHood[0, 0, 0].IsValid &&
                                                          !neighborHood[0, 0, 0].IsEmpty))
                        {
                            successors.Add(new MoveAction
                            {
                                Diff     = new Vector3(0, 1, 0),
                                MoveType = moveType
                            });
                        }
                    }
                }
            }

            // Now a somewhat tricky part. We've got to figure out which cells can jump to this cell.
            // The rules for jumping are as follows:
            // 1) The voxel must be exactly 1 below this one.
            // 2) The voxel must be exactly 1 away in the other dimensions
            // 3) The voxel above the one we're jumping from must be free.
            // 4) The voxel below the one we're jumping from must be filled, or be in water, or
            //    must be part of a climb action.
            // Step 4 is really hard, so let's ignore it for now.

            // First, check the 3x3 neighborhood around the voxel.
            if (standingOnGround)
            {
                for (int dx = 0; dx <= 2; dx++)
                {
                    for (int dz = 0; dz <= 2; dz++)
                    {
                        // Ignore the current voxel (can't jump from there)
                        if (dx == 1 && dz == 1)
                        {
                            continue;
                        }
                        // Can't jump from neighbor because neighbor's head isn't clear.
                        if (!(neighborHood[dx, 1, dz].IsValid && neighborHood[dx, 1, dz].IsEmpty))
                        {
                            continue;
                        }

                        // Now just assume we can jump from the neighbor below us. TODO (step 4)
                        successors.Add(new MoveAction
                        {
                            Diff     = new Vector3(dx, 0, dz),
                            MoveType = MoveType.Jump
                        });
                    }
                }
            }


            // If the creature is not in water and is not standing on ground,
            // it can fall one voxel downward in free space. So check the voxel above,
            // if it is free and has no water, then we could have fallen from it.
            if (neighborHood[1, 2, 1].IsValid && neighborHood[1, 2, 1].IsEmpty && neighborHood[1, 2, 1].WaterCell.WaterLevel == 0)
            {
                successors.Add(new MoveAction
                {
                    Diff     = new Vector3(1, 2, 1),
                    MoveType = MoveType.Fall
                });
            }

            // If the creature can fly and is not underwater, it can fly
            // to any adjacent empty cell. Luckily this is reversible so we don't have to change
            // anything from GetMoveactions
            if (CanFly && !inWater)
            {
                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 (!neighborHood[dx, 1, dz].IsValid || neighborHood[dx, 1, dz].IsEmpty)
                            {
                                successors.Add(new MoveAction
                                {
                                    Diff     = new Vector3(dx, dy, dz),
                                    MoveType = MoveType.Fly
                                });
                            }
                        }
                    }
                }
            }

            // Now, validate each move action that the creature might take.
            foreach (MoveAction v in successors)
            {
                var n = neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z];
                if (n.IsValid && (n.IsEmpty || n.WaterCell.WaterLevel > 0))
                {
                    // Do one final check to see if there is an object blocking the motion.
                    bool blockedByObject   = false;
                    var  objectsAtNeighbor = Creature.Manager.World.CollisionManager.EnumerateIntersectingObjects(
                        n.GetBoundingBox(), CollisionManager.CollisionType.Static);

                    // If there is an object blocking the motion, determine if it can be passed through.

                    foreach (var body in objectsAtNeighbor.OfType <GameComponent>())
                    {
                        var door = body.GetRoot().EnumerateAll().OfType <Door>().FirstOrDefault();
                        // If there is an enemy door blocking movement, we can destroy it to get through.
                        if (door != null)
                        {
                            if (
                                Creature.World.Diplomacy.GetPolitics(door.TeamFaction, Creature.Faction)
                                .GetCurrentRelationship() !=
                                Relationship.Loving)
                            {
                                if (Can(MoveType.DestroyObject))
                                {
                                    yield return(new MoveAction
                                    {
                                        Diff = -(v.Diff - Vector3.One),
                                        MoveType = MoveType.DestroyObject,
                                        InteractObject = door,
                                        DestinationVoxel = voxel,
                                        SourceVoxel = n
                                    });
                                }
                                blockedByObject = true;
                            }
                        }
                    }

                    // If no object blocked us, we can move freely as normal.
                    if (!blockedByObject)
                    {
                        MoveAction newAction = v;
                        newAction.Diff             = -(v.Diff - Vector3.One);
                        newAction.DestinationVoxel = voxel;
                        newAction.SourceVoxel      = n;
                        yield return(newAction);
                    }
                }
            }
        }
 private GameComponent GetBodyAt(VoxelHandle voxel, CollisionManager objectHash, string tag)
 {
     return(objectHash.EnumerateIntersectingObjects(voxel.GetBoundingBox(),
                                                    CollisionManager.CollisionType.Static).OfType <GameComponent>().FirstOrDefault(component => component.Tags.Contains(tag)));
 }
        /// <summary> gets the list of actions that the creature can take from a given voxel. </summary>
        public IEnumerable <MoveAction> GetMoveActions(VoxelHandle voxel)
        {
            if (!voxel.IsValid || !voxel.IsEmpty)
            {
                yield break;
            }

            CollisionManager objectHash = Creature.Manager.World.CollisionManager;

            var  neighborHood     = GetNeighborhood(voxel);
            bool inWater          = (neighborHood[1, 1, 1].IsValid && neighborHood[1, 1, 1].WaterCell.WaterLevel > WaterManager.inWaterThreshold);
            bool standingOnGround = (neighborHood[1, 0, 1].IsValid && !neighborHood[1, 0, 1].IsEmpty);
            bool topCovered       = (neighborHood[1, 2, 1].IsValid && !neighborHood[1, 2, 1].IsEmpty);
            bool hasNeighbors     = HasNeighbors(neighborHood);
            bool isClimbing       = false;

            var successors = new List <MoveAction>();

            if (CanClimb)
            {
                //Climbing ladders.
                var bodies = objectHash.EnumerateIntersectingObjects(voxel.GetBoundingBox(), CollisionManager.CollisionType.Static).OfType <GameComponent>();

                var ladder = bodies.FirstOrDefault(component => component.Tags.Contains("Climbable"));

                // if the creature can climb objects and a ladder is in this voxel,
                // then add a climb action.
                if (ladder != null)
                {
                    successors.Add(new MoveAction
                    {
                        Diff           = new Vector3(1, 2, 1),
                        MoveType       = MoveType.Climb,
                        InteractObject = ladder
                    });

                    isClimbing = true;

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

                    standingOnGround = true;
                }
            }

            // If the creature can climb walls and is not blocked by a voxl above.
            if (CanClimbWalls && !topCovered)
            {
                var walls = new VoxelHandle[]
                {
                    neighborHood[2, 1, 1], neighborHood[0, 1, 1], neighborHood[1, 1, 2],
                    neighborHood[1, 1, 0]
                };

                var wall = VoxelHandle.InvalidHandle;
                foreach (var w in walls)
                {
                    if (w.IsValid && !w.IsEmpty)
                    {
                        wall = w;
                    }
                }

                if (wall.IsValid)
                {
                    isClimbing = true;
                    successors.Add(new MoveAction
                    {
                        Diff        = new Vector3(1, 2, 1),
                        MoveType    = MoveType.ClimbWalls,
                        ActionVoxel = wall
                    });

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

            // If the creature either can walk or is in water, add the
            // eight-connected free neighbors around the voxel.
            if ((CanWalk && standingOnGround) || (CanSwim && inWater))
            {
                // If the creature is in water, it can swim. Otherwise, it will walk.
                var moveType = inWater ? MoveType.Swim : MoveType.Walk;
                if (!neighborHood[0, 1, 1].IsValid || neighborHood[0, 1, 1].IsEmpty)
                {
                    // +- x
                    successors.Add(new MoveAction
                    {
                        Diff     = new Vector3(0, 1, 1),
                        MoveType = moveType
                    });
                }

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

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

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

                // Only bother worrying about 8-connected movement if there are
                // no full neighbors around the voxel.
                if (!hasNeighbors)
                {
                    if (!neighborHood[2, 1, 2].IsValid || neighborHood[2, 1, 2].IsEmpty)
                    {
                        // +x + z
                        successors.Add(new MoveAction
                        {
                            Diff     = new Vector3(2, 1, 2),
                            MoveType = moveType
                        });
                    }

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

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

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

            // If the creature's head is free, and it is standing on ground,
            // or if it is in water, or if it is climbing, it can also jump
            // to voxels that are 1 cell away and 1 cell up.
            if (!topCovered && (standingOnGround || (CanSwim && inWater) || isClimbing))
            {
                for (int dx = 0; dx <= 2; dx++)
                {
                    for (int dz = 0; dz <= 2; dz++)
                    {
                        if (dx == 1 && dz == 1)
                        {
                            continue;
                        }

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


            // If the creature is not in water and is not standing on ground,
            // it can fall one voxel downward in free space.
            if (!inWater && !standingOnGround)
            {
                successors.Add(new MoveAction
                {
                    Diff     = new Vector3(1, 0, 1),
                    MoveType = MoveType.Fall
                });
            }

            // If the creature can fly and is not underwater, it can fly
            // to any adjacent empty cell.
            if (CanFly && !inWater)
            {
                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 (!neighborHood[dx, 1, dz].IsValid || neighborHood[dx, 1, dz].IsEmpty)
                            {
                                successors.Add(new MoveAction
                                {
                                    Diff     = new Vector3(dx, dy, dz),
                                    MoveType = MoveType.Fly
                                });
                            }
                        }
                    }
                }
            }

            // Now, validate each move action that the creature might take.
            foreach (MoveAction v in successors)
            {
                var n = neighborHood[(int)v.Diff.X, (int)v.Diff.Y, (int)v.Diff.Z];
                if (n.IsValid && (n.IsEmpty || n.WaterCell.WaterLevel > 0))
                {
                    // Do one final check to see if there is an object blocking the motion.
                    bool blockedByObject   = false;
                    var  objectsAtNeighbor = Creature.Manager.World.CollisionManager.EnumerateIntersectingObjects(
                        n.GetBoundingBox(), CollisionManager.CollisionType.Static);

                    // If there is an object blocking the motion, determine if it can be passed through.

                    foreach (var body in objectsAtNeighbor.OfType <GameComponent>())
                    {
                        var door = body.GetRoot().EnumerateAll().OfType <Door>().FirstOrDefault();
                        // If there is an enemy door blocking movement, we can destroy it to get through.
                        if (door != null)
                        {
                            if (
                                Creature.World.Diplomacy.GetPolitics(door.TeamFaction, Creature.Faction)
                                .GetCurrentRelationship() !=
                                Relationship.Loving)
                            {
                                if (Can(MoveType.DestroyObject))
                                {
                                    yield return(new MoveAction
                                    {
                                        Diff = v.Diff,
                                        MoveType = MoveType.DestroyObject,
                                        InteractObject = door,
                                        DestinationVoxel = n,
                                        SourceVoxel = voxel
                                    });
                                }
                                blockedByObject = true;
                            }
                        }
                    }

                    // If no object blocked us, we can move freely as normal.
                    if (!blockedByObject)
                    {
                        MoveAction newAction = v;
                        newAction.SourceVoxel      = voxel;
                        newAction.DestinationVoxel = n;
                        yield return(newAction);
                    }
                }
            }
        }
Exemple #6
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);
        }
Exemple #7
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;
        }