public void PopulateChunk(World world, Chunk chunk, ChunkPosition position) { var rand = new Random((int)world.Seed); var perlin = new PerlinNoiseOctaveHelper((rand.Next() << 16) | rand.Next(), 8, 3); var mountainPerlin = new PerlinNoiseOctaveHelper((rand.Next() << 16) | rand.Next(), 8, 3); var cavePerlin = new PerlinNoiseOctaveHelper((rand.Next() << 16) | rand.Next(), 5, 3); var temperaturePerlin = new PerlinNoiseOctaveHelper((rand.Next() << 16) | rand.Next(), 5, 3); var humidityPerlin = new PerlinNoiseOctaveHelper((rand.Next() << 16) | rand.Next(), 5, 3); if (!StaticReferences.ParallelMode) { for (byte x = 0; x < 16; x++) { for (byte z = 0; z < 16; z++) { PerlinGeneration(world.Seed, chunk, position, perlin, mountainPerlin, cavePerlin, temperaturePerlin, humidityPerlin, x, z); } } } else { Parallel.For(0, 256, (i) => { PerlinGeneration(world.Seed, chunk, position, perlin, mountainPerlin, cavePerlin, temperaturePerlin, humidityPerlin, (byte)(i % 16), (byte)(i / 16)); }); } }
public void SetChunkToUnload(World world, int x, int z) { var chunkBlockPosition = new ChunkPosition((int)Math.Floor(x / 8f), (int)Math.Floor(z / 8f)); Chunk[] chunkBlock; if (world.ChunkBlocks.TryGetValue(chunkBlockPosition, out chunkBlock)) { var chunkIndex = (((x & 7) << 3) + (z & 7)); if (chunkBlock[chunkIndex] != null) { world.ChunksToUnload.Add(chunkBlock[chunkIndex]); chunkBlock[chunkIndex] = null; for (int i = 0; i < chunkBlock.Length; i++) { if (chunkBlock[i] != null) { return; } } Chunk[] tmp; world.ChunkBlocks.TryRemove(chunkBlockPosition, out tmp); } } }
public Chunk[] GetSiblingChunks(World world, ChunkPosition chunkPosition) { var chunks = new Chunk[4]; chunks[0] = DirectGetChunk(world, chunkPosition.X - 1, chunkPosition.Z); chunks[1] = DirectGetChunk(world, chunkPosition.X, chunkPosition.Z + 1); chunks[2] = DirectGetChunk(world, chunkPosition.X + 1, chunkPosition.Z); chunks[3] = DirectGetChunk(world, chunkPosition.X, chunkPosition.Z - 1); return(chunks); }
private void CheckInvalidations(World world, Chunk chunk, ChunkPosition chunkPosition) { if (chunk.ChunkParts.Any(cp => cp.Invalidated)) { for (int i = 0; i < chunk.ChunkParts.Length; i++) { var chunkPart = chunk.ChunkParts[i]; if (chunkPart.Invalidated) { ComputeBlocks(world, chunk, chunkPart, i, chunkPosition); } } } }
public Chunk DirectGetChunk(World world, int x, int z) { var chunkBlockPosition = new ChunkPosition((int)Math.Floor(x / 8f), (int)Math.Floor(z / 8f)); Chunk[] chunkBlock; if (world.ChunkBlocks.TryGetValue(chunkBlockPosition, out chunkBlock)) { var chunkIndex = (((x & 7) << 3) + (z & 7)); if (chunkBlock[chunkIndex] != null) { return(chunkBlock[chunkIndex]); } } return(null); }
private bool ComputeBlockInfo(Chunk chunk, ChunkPosition chunkPosition, Chunk[] siblingChunks, byte x, byte z, short y, Chunk.ChunkBlockInformation chunkBlockInformation, out BlockInfo?blockInfo) { var blockVisibility = _blocksProvider.GetBlockForId(chunkBlockInformation.Id).IsOpaque ? 0 : 0x3F00; if (blockVisibility == 0) { if ((x > 0 && _blocksProvider.GetBlockForId(_chunkManager.GetBlockId(chunk, (byte)(x - 1), (byte)y, z))?.IsOpaque != true) || (x == 0 && _blocksProvider.GetBlockForId(siblingChunks[0] != null ? _chunkManager.GetBlockId(siblingChunks[0], 15, (byte)y, z) : (byte)0)?.IsOpaque != true)) { blockVisibility |= (int)BlockVisibility.Left; } if ((x < 15 && _blocksProvider.GetBlockForId(_chunkManager.GetBlockId(chunk, (byte)(x + 1), (byte)y, z))?.IsOpaque != true) || (x == 15 && _blocksProvider.GetBlockForId(siblingChunks[2] != null ? _chunkManager.GetBlockId(siblingChunks[2], 0, (byte)y, z) : (byte)0)?.IsOpaque != true)) { blockVisibility |= (int)BlockVisibility.Right; } if ((z > 0 && _blocksProvider.GetBlockForId(_chunkManager.GetBlockId(chunk, x, (byte)y, (byte)(z - 1)))?.IsOpaque != true) || (z == 0 && _blocksProvider.GetBlockForId(siblingChunks[3] != null ? _chunkManager.GetBlockId(siblingChunks[3], x, (byte)y, 15) : (byte)0)?.IsOpaque != true)) { blockVisibility |= (int)BlockVisibility.Front; } if ((z < 15 && _blocksProvider.GetBlockForId(_chunkManager.GetBlockId(chunk, x, (byte)y, (byte)(z + 1)))?.IsOpaque != true) || (z == 15 && _blocksProvider.GetBlockForId(siblingChunks[1] != null ? _chunkManager.GetBlockId(siblingChunks[1], x, (byte)y, 0) : (byte)0)?.IsOpaque != true)) { blockVisibility |= (int)BlockVisibility.Back; } if (y == 0 || _blocksProvider.GetBlockForId(_chunkManager.GetBlockId(chunk, x, (byte)(y - 1), z))?.IsOpaque != true) { blockVisibility |= (int)BlockVisibility.Bottom; } if (y == 255 || _blocksProvider.GetBlockForId(_chunkManager.GetBlockId(chunk, x, (byte)(y + 1), z))?.IsOpaque != true) { blockVisibility |= (int)BlockVisibility.Top; } } if (blockVisibility != 0) { blockInfo = new BlockInfo { BlockIdAndBlockVisibilityAndMetadata = blockVisibility | chunkBlockInformation.Id | (chunkBlockInformation.Metadata << 14), HumidityAndTemperature = chunkBlockInformation.Humidity << 8 | chunkBlockInformation.Temperature, Position = new Vector3((chunkPosition.X << 4) + x, y, (chunkPosition.Z << 4) + z) }; return(true); } blockInfo = null; return(false); }
private Chunk ProvideChunk(World world, int x, int z) { var position = new ChunkPosition(x, z); var chunkBlockPosition = new ChunkPosition((int)Math.Floor(x / 8f), (int)Math.Floor(z / 8f)); Chunk[] chunkBlock; if (!world.ChunkBlocks.TryGetValue(chunkBlockPosition, out chunkBlock)) { chunkBlock = new Chunk[8 * 8]; world.ChunkBlocks.TryAdd(chunkBlockPosition, chunkBlock); } var chunkIndex = (((x & 7) << 3) + (z & 7)); if (chunkBlock[chunkIndex] != null) { return(chunkBlock[chunkIndex]); } var newChunk = new Chunk(); _chunkGenerator.PopulateChunk(world, newChunk, position); chunkBlock[chunkIndex] = newChunk; var chunk = DirectGetChunk(world, x - 1, z); if (chunk != null) { _chunkManager.Invalidate(chunk); } chunk = DirectGetChunk(world, x + 1, z); if (chunk != null) { _chunkManager.Invalidate(chunk); } chunk = DirectGetChunk(world, x, z - 1); if (chunk != null) { _chunkManager.Invalidate(chunk); } chunk = DirectGetChunk(world, x, z + 1); if (chunk != null) { _chunkManager.Invalidate(chunk); } return(newChunk); }
private void ComputeBlocks(World world, Chunk chunk, Chunk.ChunkPart chunkPart, int partNumber, ChunkPosition chunkPosition) { if (chunkPart.Blocks != null) { StaticReferences.BlocksToClean.Add(chunkPart.Blocks); } chunkPart.Blocks = new Blocks3D(); var partNumberMultipliedBy16 = partNumber << 4; var siblingChunks = _worldManager.GetSiblingChunks(world, chunkPosition); if (StaticReferences.ParallelMode) { var blockInfos = new List <BlockInfo> [256]; Parallel.For(0, 256, (i) => { var x = (byte)(i % 16); var z = (byte)(i / 16); var bInfos = new List <BlockInfo>(64); for (short y = (short)partNumberMultipliedBy16; y < partNumberMultipliedBy16 + 16; y++) { var chunkBlockInfo = _chunkManager.GetBlockInformation(chunk, x, (byte)y, z); if (chunkBlockInfo.Id == 0) { continue; } BlockInfo?blockInfo; if (ComputeBlockInfo(chunk, chunkPosition, siblingChunks, x, z, y, chunkBlockInfo, out blockInfo)) { bInfos.Add((BlockInfo)blockInfo); } } blockInfos[i] = bInfos; }); for (int i = 0; i < 256; i++) { chunkPart.Blocks.BlockInfos.AddRange(blockInfos[i]); } } else { for (byte x = 0; x < 16; x++) { for (byte z = 0; z < 16; z++) { for (short y = (short)partNumberMultipliedBy16; y < partNumberMultipliedBy16 + 16; y++) { var chunkBlockInfo = _chunkManager.GetBlockInformation(chunk, x, (byte)y, z); if (chunkBlockInfo.Id == 0) { continue; } BlockInfo?blockInfo; if (ComputeBlockInfo(chunk, chunkPosition, siblingChunks, x, z, y, chunkBlockInfo, out blockInfo)) { chunkPart.Blocks.BlockInfos.Add((BlockInfo)blockInfo); } } } } } chunkPart.Invalidated = false; }
private void PerlinGeneration(long seed, Chunk chunk, ChunkPosition position, PerlinNoiseOctaveHelper perlin, PerlinNoiseOctaveHelper mountainPerlin, PerlinNoiseOctaveHelper cavePerlin, PerlinNoiseOctaveHelper temperaturePerlin, PerlinNoiseOctaveHelper humidityPerlin, byte x, byte z) { var rand = new Random((int)seed); rand = new Random((position.X * 16 + x) * rand.Next() * (position.Z * 16 + z) * rand.Next()); var frequency = 0.0005f; var moutainFrequency = 0.00005f; var caveFrequency = 0.003f; var temperatureFrequency = 0.0003f; var temperature = (byte)MAX(MIN(MAP((float)temperaturePerlin.Noise((position.X * 16 + x) * temperatureFrequency, 0, (position.Z * 16 + z) * temperatureFrequency), -0.5f, 0.5f, 0, 255), 255), 0); _chunkManager.SetTemperature(chunk, x, z, temperature); var humidityFrequency = 0.0003f; var humidity = (byte)MAX(MIN(MAP((float)humidityPerlin.Noise((position.X * 16 + x) * humidityFrequency, 0, (position.Z * 16 + z) * humidityFrequency), -0.5f, 0.5f, 0, 255), 255), 0); _chunkManager.SetHumidity(chunk, x, z, humidity); var perlinResult = perlin.Noise(((position.X * 16 + x)) * frequency, 0, ((position.Z * 16 + z)) * frequency); var mountainPerlinResult = mountainPerlin.Noise(((position.X * 16 + x)) * moutainFrequency, 0, ((position.Z * 16 + z)) * moutainFrequency); var perlinHeight = MAP((float)perlinResult, -0.5f, 0.5f, 60, 70) * MAP((float)((mountainPerlinResult + 0.5f) * (temperature / 255f)), 0, 1f, 0.5f, 4); if (perlinHeight < 0) { perlinHeight = 0; } else if (perlinHeight > 255) { perlinHeight = 255; } byte height = (byte)perlinHeight; for (byte y = 0; y < height; y++) { var cavePerlinResult = ((float)cavePerlin.Noise(((position.X * 16 + x)) * caveFrequency, y * caveFrequency, ((position.Z * 16 + z)) * caveFrequency) + 0.5f) * ((y) / 64f); cavePerlinResult = MIN(MAP(cavePerlinResult, 0f, 0.1f, 0.1f, 0.2f), cavePerlinResult); if (cavePerlinResult > 0.04f) { if (temperature > 160 || humidity > 64) { if (y == height - 1) { if (y > 0 && _chunkManager.GetBlockId(chunk, x, (byte)(y - 1), z) != 0 && rand.Next(10) == 0) { _chunkManager.SetBlockId(chunk, x, y, z, 31); } } else if (y == height - 2) { _chunkManager.SetBlockId(chunk, x, y, z, 2); } else if (y >= height - 5) { _chunkManager.SetBlockId(chunk, x, y, z, 3); } else { _chunkManager.SetBlockId(chunk, x, y, z, 1); } } else { if (y == height - 1) { if (rand.Next(30) == 0) { _chunkManager.SetBlockId(chunk, x, y, z, 31); } } else if (y < height - 1 && y >= height - 4) { _chunkManager.SetBlockId(chunk, x, y, z, 12); } else if (y >= height - 6) { _chunkManager.SetBlockId(chunk, x, y, z, 24); } else { _chunkManager.SetBlockId(chunk, x, y, z, 1); } } } } }