Пример #1
0
        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));
                });
            }
        }
Пример #2
0
        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);
                }
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
 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);
             }
         }
     }
 }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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;
        }
Пример #9
0
        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);
                        }
                    }
                }
            }
        }