private GeneratedChunk[,,] Generate(Range3I range) { if (_processors.Count == 0) { throw new InvalidOperationException("Add at least one genereation process (stage) before starting"); } var chunks = new GeneratedChunk[range.Size.X, range.Size.Y, range.Size.Z]; for (int x = 0; x < range.Size.X; x++) { for (int y = 0; y < range.Size.Y; y++) { for (int z = 0; z < range.Size.Z; z++) { chunks[x, y, z] = new GeneratedChunk { Position = new Vector3I(x + range.Position.X, y + range.Position.Y, z + range.Position.Z) }; } } } foreach (var processor in _processors) { processor.Generate(range, chunks); } return(chunks); }
/// <summary> /// Will Populate the chunks with various resources /// </summary> /// <param name="ChunkCubes"></param> /// <param name="chunkMetaData"></param> private void PopulateChunk(GeneratedChunk chunk, byte[] chunkData, ChunkMetaData chunkMetaData, FastRandom chunkRnd, EntityFactory entityFactory, List <LandscapeEntity> landscapeEntities) { //Get Chunk Master Biome var masterBiome = _config.ProcessorParam.Biomes[chunkMetaData.ChunkMasterBiomeType]; ByteChunkCursor dataCursor = new ByteChunkCursor(chunkData, chunk.BlockData.ColumnsInfo); masterBiome.GenerateChunkCaverns(dataCursor, chunkRnd); masterBiome.GenerateChunkResources(dataCursor, chunkRnd); chunkMetaData.InitialSpawnableEntitiesAmount = masterBiome.GenerateChunkStaticItems(dataCursor, chunk, masterBiome, chunkRnd, entityFactory, _spawnControler); InsertMicrolandscapeStaticEntities(dataCursor, chunk, chunkRnd, entityFactory, landscapeEntities); }
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> /// Creates new instance of the server chunk from generator /// </summary> /// <param name="chunk"></param> public ServerChunk(GeneratedChunk chunk) : base(chunk.BlockData) { Entities.Import(chunk.Entities); PureGenerated = true; }
/// <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--; } } } }
//Will send back a dictionnary with the entity amount that have been generated public Dictionary <ushort, int> GenerateChunkStaticItems(ByteChunkCursor cursor, GeneratedChunk chunk, Biome biome, FastRandom rnd, EntityFactory entityFactory, UtopiaEntitySpawningControler spawnControler) { Dictionary <ushort, int> entityAmount = new Dictionary <ushort, int>(); foreach (ChunkSpawnableEntity entity in SpawnableEntities.Where(x => x.IsChunkGenerationSpawning)) { for (int i = 0; i < entity.MaxEntityAmount; i++) { Vector3D entityPosition; if (spawnControler.TryGetSpawnLocation(entity, chunk, cursor, rnd, out entityPosition)) { //Create the entity var createdEntity = entityFactory.CreateFromBluePrint(entity.BluePrintId); var chunkWorldPosition = chunk.BlockPosition; //Should take into account the SpawnLocation ! (Ceiling or not !) if (createdEntity is IBlockLinkedEntity) { Vector3I linkedCubePosition = BlockHelper.EntityToBlock(entityPosition); linkedCubePosition.Y--; ((IBlockLinkedEntity)createdEntity).LinkedCube = linkedCubePosition; } if (createdEntity is BlockLinkedItem) { Vector3I LocationCube = BlockHelper.EntityToBlock(entityPosition); ((BlockLinkedItem)createdEntity).BlockLocationRoot = LocationCube; } createdEntity.Position = entityPosition; chunk.Entities.Add((StaticEntity)createdEntity); if (!entityAmount.ContainsKey(createdEntity.BluePrintId)) { entityAmount[createdEntity.BluePrintId] = 0; } entityAmount[createdEntity.BluePrintId]++; } } } return(entityAmount); }