private bool CaveSpawnLogic(int x, int z, ChunkSpawnableEntity entity, AbstractChunk chunk, ByteChunkCursor cursor, FastRandom rnd, out Vector3D entitySpawnLocation) { entitySpawnLocation = default(Vector3D); int y; int columnInfoIndex = x * AbstractChunk.ChunkSize.Z + z; cursor.SetInternalPosition(x, 1, z); //Move up until Air Block while (cursor.Read() != WorldConfiguration.CubeId.Air) { //Move up, if top chunk height exit if (cursor.Move(CursorRelativeMovement.Up) == false) { return(false); } } int YFloorSpawning = cursor.InternalPosition.Y; int MaximumSpawningHeight = chunk.BlockData.ColumnsInfo[columnInfoIndex].MaxGroundHeight - 10; if (MaximumSpawningHeight <= 0) { MaximumSpawningHeight = 1; } //Move up until "solid" Block while (cursor.Read() == WorldConfiguration.CubeId.Air && cursor.InternalPosition.Y <= MaximumSpawningHeight) { //Move up, if top chunk height exit if (cursor.Move(CursorRelativeMovement.Up) == false) { return(false); } } if (cursor.InternalPosition.Y > MaximumSpawningHeight) { return(false); } // Hurray it can spawn ! :D //Add some randomnes on the cube where it will spawn double XOffset, ZOffset; XOffset = rnd.NextDouble(0.2, 0.8); ZOffset = rnd.NextDouble(0.2, 0.8); if (entity.SpawningPlace == ChunkSpawningPlace.FloorInsideCave) { entitySpawnLocation = new Vector3D(chunk.BlockPosition.X + x + XOffset, YFloorSpawning, chunk.BlockPosition.Z + z + ZOffset); } else { entitySpawnLocation = new Vector3D(chunk.BlockPosition.X + x + XOffset, cursor.InternalPosition.Y - 1, chunk.BlockPosition.Z + z + ZOffset); } return(true); }
private bool SurfaceSpawnLogic(int x, int z, ChunkSpawnableEntity entity, AbstractChunk chunk, ByteChunkCursor cursor, FastRandom rnd, out Vector3D entitySpawnLocation) { entitySpawnLocation = default(Vector3D); int y; int columnInfoIndex = x * AbstractChunk.ChunkSize.Z + z; //Y base = Original world generated ground height (Before any player modification) y = chunk.BlockData.ColumnsInfo[columnInfoIndex].MaxGroundHeight; cursor.SetInternalPosition(x, y, z); // verify that we can spawn here var canSpawn = cursor.Read() != WorldConfiguration.CubeId.Air && cursor.Move(CursorRelativeMovement.Up) && cursor.Read() == WorldConfiguration.CubeId.Air && cursor.Move(CursorRelativeMovement.Up) && cursor.Read() == WorldConfiguration.CubeId.Air; // return cursor to the spawn point cursor.Move(CursorRelativeMovement.Down); if (!canSpawn) { return(false); } // Check that the block is well "Solid to entity" BlockProfile blockSpawnProfile = _config.BlockProfiles[cursor.Peek(CursorRelativeMovement.Down)]; if (!blockSpawnProfile.IsSolidToEntity) { return(false); } if (entity.IsWildChunkNeeded) { //Get Chunk master biome byte masterBiomeId = chunk.BlockData.ChunkMetaData.ChunkMasterBiomeType; //Get biome surface block layer byte surfaceBiomeCube = _config.ProcessorParam.Biomes[masterBiomeId].SurfaceCube; //If the entity need a Wild chunk, then it can only spawn on a cube surface equal to the default biome surface cube ! if (surfaceBiomeCube != blockSpawnProfile.Id) { return(false); } } // Hurray it can spawn ! :D //Add some randomnes on the cube where it will spawn double XOffset, ZOffset; XOffset = rnd.NextDouble(0.2, 0.8); ZOffset = rnd.NextDouble(0.2, 0.8); entitySpawnLocation = new Vector3D(chunk.BlockPosition.X + x + XOffset, cursor.InternalPosition.Y, chunk.BlockPosition.Z + z + ZOffset); return(true); }
private bool AirSpawnLogic(int x, int z, ChunkSpawnableEntity entity, AbstractChunk chunk, ByteChunkCursor cursor, FastRandom rnd, out Vector3D entitySpawnLocation) { entitySpawnLocation = default(Vector3D); int y; int columnInfoIndex = x * AbstractChunk.ChunkSize.Z + z; //Y base = Original world generated ground height (Before any player modification) y = rnd.Next(chunk.BlockData.ColumnsInfo[columnInfoIndex].MaxHeight + 5, AbstractChunk.ChunkSize.Y); if (y <= 0 || y >= AbstractChunk.ChunkSize.Y) { return(false); } cursor.SetInternalPosition(x, y, z); if (cursor.Read() != WorldConfiguration.CubeId.Air) { return(false); } // Hurray it can spawn ! :D //Add some randomnes on the cube where it will spawn double XOffset, ZOffset; XOffset = rnd.NextDouble(0.2, 0.8); ZOffset = rnd.NextDouble(0.2, 0.8); entitySpawnLocation = new Vector3D(chunk.BlockPosition.X + x + XOffset, cursor.InternalPosition.Y, chunk.BlockPosition.Z + z + ZOffset); return(true); }
private void PopulateChunkWithCave(ByteChunkCursor cursor, int x, int y, int z, int layers, byte cubeId, FastRandom rnd) { cursor.SetInternalPosition(x, y, z); int caveRadius = rnd.Next(3, 8); int layerRadiusModifier = 0; for (int l = 0; l < layers; l++) { //Generate Lake Layers for (int X = x - (caveRadius - layerRadiusModifier); X <= x + (caveRadius - layerRadiusModifier); X++) { for (int Z = z - (caveRadius - layerRadiusModifier); Z <= z + (caveRadius - layerRadiusModifier); Z++) { //Create "Noise" at Cave border if ((X == x - (caveRadius - layerRadiusModifier) || X == x + (caveRadius - layerRadiusModifier) || Z == z - (caveRadius - layerRadiusModifier) || Z == z + (caveRadius - layerRadiusModifier)) && rnd.NextDouble() < 0.2) { continue; } cursor.SetInternalPosition(X, y + l, Z); if (l <= 1 && rnd.NextDouble() < 0.3) { cursor.Write(cubeId); } else { if (l != 0) { if (l == layers - 1) { if (cursor.Read() == UtopiaProcessorParams.CubeId.Stone) { cursor.Write(UtopiaProcessorParams.CubeId.LightWhite); } } else { cursor.Write(UtopiaProcessorParams.CubeId.Air); } } } } } if (layerRadiusModifier < caveRadius) { layerRadiusModifier++; } } }
/// <summary> /// Will create a resource vein /// </summary> /// <param name="cubeId">The resource to be created</param> /// <param name="cursor">Class helper to move inside the Chunk cube data</param> /// <param name="x">InsideChunk X starting position</param> /// <param name="y">InsideChunk Y starting position</param> /// <param name="z">InsideChunk Z starting position</param> /// <param name="qt">Vein size</param> /// <param name="rnd">Random generator for vein creation</param> private void PopulateChunkWithResource(byte cubeId, ByteChunkCursor cursor, int x, int y, int z, int qt, FastRandom rnd) { cursor.SetInternalPosition(x, y, z); int nbrCubePlaced; if (cursor.Read() == UtopiaProcessorParams.CubeId.Stone) { cursor.Write(cubeId); nbrCubePlaced = 1; for (int i = 0; i < qt + 10 && nbrCubePlaced < qt; i++) { int relativeMove = rnd.Next(1, 7); cursor.Move(relativeMove); if (cursor.Read() == UtopiaProcessorParams.CubeId.Stone) { cursor.Write(cubeId); nbrCubePlaced++; } } } }
/// <summary> /// Will create a single Liquid "Source" /// </summary> /// <param name="cubeId">the liquid CubeId</param> /// <param name="cursor">Class helper to move inside the chunk</param> /// <param name="x">InsideChunk X starting position</param> /// <param name="y">InsideChunk Y starting position</param> /// <param name="z">InsideChunk Z starting position</param> private void PopulateChunkWithLiquidSources(byte cubeId, ByteChunkCursor cursor, int x, int y, int z, int liquidPower) { cursor.SetInternalPosition(x, y, z); //Check if this source is candidate as valid source = Must be surrended by 5 solid blocks and ahave one side block going to Air if (cursor.Read() != UtopiaProcessorParams.CubeId.Air) { //Looking Up for Air if (_config.BlockProfiles[cursor.Peek(CursorRelativeMovement.Up)].IsBlockingWater == false || cursor.Peek(CursorRelativeMovement.Up) == UtopiaProcessorParams.CubeId.Snow) { return; } if (_config.BlockProfiles[cursor.Peek(CursorRelativeMovement.Down)].IsBlockingWater == false) { return; } int cpt = 0; //Counting the number of holes arround the source if (_config.BlockProfiles[cursor.Peek(CursorRelativeMovement.East)].IsBlockingWater == false) { cpt++; } if (_config.BlockProfiles[cursor.Peek(CursorRelativeMovement.West)].IsBlockingWater == false) { cpt++; } if (_config.BlockProfiles[cursor.Peek(CursorRelativeMovement.North)].IsBlockingWater == false) { cpt++; } if (_config.BlockProfiles[cursor.Peek(CursorRelativeMovement.South)].IsBlockingWater == false) { cpt++; } //Only one face touching air ==> Createing the Liquid Source ! if (cpt != 1) { return; } cursor.Write(cubeId); Queue <Tuple <ByteChunkCursor, int> > sourcesWithPower = new Queue <Tuple <ByteChunkCursor, int> >(); sourcesWithPower.Enqueue(new Tuple <ByteChunkCursor, int>(cursor, liquidPower)); PropagateLiquidSources(sourcesWithPower, cubeId); } }
private void PopulateChunkWithItems(ByteChunkCursor cursor, GeneratedChunk chunk, ref Vector3D chunkWorldPosition, ushort bluePrintId, int x, int y, int z, FastRandom rnd, EntityFactory entityFactory, bool isBlockCentered = true) { cursor.SetInternalPosition(x, y, z); //Check that the block above is "Air" if (cursor.Peek(CursorRelativeMovement.Up) != UtopiaProcessorParams.CubeId.Air) { return; } //Check that the block below is "solid" byte blockBelow = cursor.Read(); BlockProfile blockBelowProfile = _config.BlockProfiles[blockBelow]; if (blockBelowProfile.IsSolidToEntity) { //Cloning the Entity Blue Print ! var entity = entityFactory.CreateFromBluePrint(bluePrintId); if (entity is IBlockLinkedEntity) { Vector3I linkedCubePosition = new Vector3I(chunkWorldPosition.X + x, y, chunkWorldPosition.Z + z); ((IBlockLinkedEntity)entity).LinkedCube = linkedCubePosition; } if (entity is BlockLinkedItem) { Vector3I LocationCube = new Vector3I(chunkWorldPosition.X + x, y + 1, chunkWorldPosition.Z + z); ((BlockLinkedItem)entity).BlockLocationRoot = LocationCube; } double XOffset = 0.5; double ZOffset = 0.5; if (isBlockCentered == false) { XOffset = rnd.NextDouble(0.2, 0.8); ZOffset = rnd.NextDouble(0.2, 0.8); } entity.Position = new Vector3D(chunkWorldPosition.X + x + XOffset, y + 1, chunkWorldPosition.Z + z + ZOffset); chunk.Entities.Add((StaticEntity)entity); } }
/// <summary> /// Will insert associated static entities from a landscape entity. /// Ex : /// For the landscape entity "Tree", multiple static entities can be found "around" it : apple, stick, banana, ... /// </summary> /// <param name="dataCursor"></param> /// <param name="chunk"></param> /// <param name="chunkRnd"></param> /// <param name="entityFactory"></param> /// <param name="landscapeEntities"></param> private void InsertMicrolandscapeStaticEntities(ByteChunkCursor dataCursor, GeneratedChunk chunk, FastRandom chunkRnd, EntityFactory entityFactory, List <LandscapeEntity> landscapeEntities) { if (landscapeEntities == null) { return; } Vector2I chunkWorldPosition = new Vector2I(chunk.Position.X * AbstractChunk.ChunkSize.X, chunk.Position.Z * AbstractChunk.ChunkSize.Z); //The entities are sorted by their origine chunk hashcode value foreach (LandscapeEntity entity in landscapeEntities) { bool isLandscapeEntityRootInsideChunk = (entity.RootLocation.X >= 0 && entity.RootLocation.X < AbstractChunk.ChunkSize.X && entity.RootLocation.Z >= 0 && entity.RootLocation.Z < AbstractChunk.ChunkSize.Z); //Get LandscapeEntity var landscapeEntity = _worldParameters.Configuration.LandscapeEntitiesDico[entity.LandscapeEntityId]; foreach (var staticEntity in landscapeEntity.StaticItems) { //Get number of object var nbr = chunkRnd.Next(staticEntity.Quantity.Min, staticEntity.Quantity.Max); if (isLandscapeEntityRootInsideChunk) { //This entity location is inside the correct chunk. //Its a tree ! if (landscapeEntity is TreeBluePrint) { //Create tree soul and attach this entity to the chunk var soul = entityFactory.CreateEntity <TreeSoul>(); soul.Position = new Vector3D(chunkWorldPosition.X + entity.RootLocation.X + 0.5, entity.RootLocation.Y, chunkWorldPosition.Y + entity.RootLocation.Z + 0.5); soul.TreeRndSeed = entity.GenerationSeed; soul.TreeTypeId = entity.LandscapeEntityId; chunk.Entities.Add(soul); } } else { //If Root out of chunk, devide the qt of object to spawn by 2 nbr = (int)(nbr / 2.0); } //Foreach object to create while (nbr > 0) { //find location of the static entity double x = chunkRnd.NextDouble(-staticEntity.SpawningRange, staticEntity.SpawningRange) + entity.RootLocation.X; double z = chunkRnd.NextDouble(-staticEntity.SpawningRange, staticEntity.SpawningRange) + entity.RootLocation.Z; //If out of current chunk, don't create it if (x < 0 || x >= AbstractChunk.ChunkSize.X || z < 0 || z >= AbstractChunk.ChunkSize.Z) { break; } bool groundSpawing; if (staticEntity.SpawningType == SpawningType.Both) { groundSpawing = chunkRnd.NextFloat() > 0.5; } else { groundSpawing = staticEntity.SpawningType == SpawningType.Ground; } StaticEntity landscapeStaticEntity = null; //Find Y spawning position if (groundSpawing) { dataCursor.SetInternalPosition(MathHelper.Floor(x), entity.RootLocation.Y, MathHelper.Floor(z)); //Loop until I hit the ground, with a maximum of Y - 15 blocks for (int y = entity.RootLocation.Y; y > entity.RootLocation.Y - 15 && y > 0; y--) { if (dataCursor.Read() != WorldConfiguration.CubeId.Air) { //Add Static item here on the ground ! landscapeStaticEntity = (StaticEntity)entityFactory.CreateFromBluePrint(staticEntity.ItemblueprintId); landscapeStaticEntity.Position = new Vector3D(x + chunkWorldPosition.X, dataCursor.InternalPosition.Y + 1, z + chunkWorldPosition.Y); break; } dataCursor.Move(CursorRelativeMovement.Down); } } else { dataCursor.SetInternalPosition(MathHelper.Floor(x), entity.RootLocation.Y + 1, MathHelper.Floor(z)); //Loop until I hit the ground, with a maximum of Y + 15 blocks for (int y = entity.RootLocation.Y + 1; y <= entity.RootLocation.Y + 15 && y < AbstractChunk.ChunkSize.Y; y++) { if (dataCursor.Read() != WorldConfiguration.CubeId.Air) { //Add Static item here on the ground ! landscapeStaticEntity = (StaticEntity)entityFactory.CreateFromBluePrint(staticEntity.ItemblueprintId); landscapeStaticEntity.Position = new Vector3D(x + chunkWorldPosition.X, dataCursor.InternalPosition.Y - 0.25, z + chunkWorldPosition.Y); break; } dataCursor.Move(CursorRelativeMovement.Up); } } if (landscapeStaticEntity != null) { chunk.Entities.Add(landscapeStaticEntity); } nbr--; } } } }