Example #1
0
        public override void GenDeposit(IBlockAccessor blockAccessor, IServerChunk[] chunks, int chunkX, int chunkZ, BlockPos depoCenterPos, ref Dictionary <BlockPos, DepositVariant> subDepositsToPlace)
        {
            int depositGradeIndex = PlaceBlock.MaxGrade == 0 ? 0 : DepositRand.NextInt(PlaceBlock.MaxGrade);

            int radius = Math.Min(64, (int)Radius.nextFloat(1, DepositRand));

            if (radius <= 0)
            {
                return;
            }


            // Let's deform that perfect circle a bit (+/- 25%)
            float deform = GameMath.Clamp(DepositRand.NextFloat() - 0.5f, -0.25f, 0.25f);

            radiusX = radius - (int)(radius * deform);
            radiusZ = radius + (int)(radius * deform);


            int baseX = chunkX * chunksize;
            int baseZ = chunkZ * chunksize;


            // No need to caluclate further if this deposit won't be part of this chunk
            if (depoCenterPos.X + radiusX < baseX - 6 || depoCenterPos.Z + radiusZ < baseZ - 6 || depoCenterPos.X - radiusX >= baseX + chunksize + 6 || depoCenterPos.Z - radiusZ >= baseZ + chunksize + 6)
            {
                return;
            }

            IMapChunk heremapchunk = chunks[0].MapChunk;


            beforeGenDeposit(heremapchunk, depoCenterPos);

            // Ok generate
            float th = Thickness.nextFloat(1, DepositRand);

            depoitThickness = (int)th + (DepositRand.NextFloat() < th - (int)th ? 1 : 0);

            float xRadSqInv = 1f / (radiusX * radiusX);
            float zRadSqInv = 1f / (radiusZ * radiusZ);

            bool parentBlockOk = false;
            ResolvedDepositBlock resolvedPlaceBlock = null;


            bool shouldGenSurfaceDeposit = DepositRand.NextFloat() <= GenSurfaceBlockChance && SurfaceBlock != null;

            int lx = GameMath.Mod(depoCenterPos.X, chunksize);
            int lz = GameMath.Mod(depoCenterPos.Z, chunksize);
            int distx, distz;

            // No need to go search far beyond chunk boundaries
            int minx = baseX - 6;
            int maxx = baseX + chunksize + 6;
            int minz = baseZ - 6;
            int maxz = baseZ + chunksize + 6;

            minx = GameMath.Clamp(depoCenterPos.X - radiusX, minx, maxx);
            maxx = GameMath.Clamp(depoCenterPos.X + radiusX, minx, maxx);
            minz = GameMath.Clamp(depoCenterPos.Z - radiusZ, minz, maxz);
            maxz = GameMath.Clamp(depoCenterPos.Z + radiusZ, minz, maxz);

            //int placed = 0;

            float  invChunkAreaSize = 1f / (chunksize * chunksize);
            double val = 1;

            for (int posx = minx; posx < maxx; posx++)
            {
                targetPos.X = posx;
                lx          = targetPos.X - baseX;
                distx       = posx - depoCenterPos.X;

                float xSq = distx * distx * xRadSqInv;

                for (int posz = minz; posz < maxz; posz++)
                {
                    targetPos.Y = depoCenterPos.Y;
                    targetPos.Z = posz;
                    lz          = targetPos.Z - baseZ;
                    distz       = posz - depoCenterPos.Z;


                    // Kinda weird mathematically speaking, but seems to work as a means to distort the perfect circleness of deposits ¯\_(ツ)_/¯
                    // Also not very efficient to use direct perlin noise in here :/
                    // But after ~10 hours of failing (=weird lines of missing deposit material) with a pre-generated 2d distortion map i give up >.>
                    val = 1 - (radius > 3 ? DistortNoiseGen.Noise(targetPos.X / 3.0, targetPos.Z / 3.0) * 0.2 : 0);
                    double distanceToEdge = val - (xSq + distz * distz * zRadSqInv);

                    if (distanceToEdge < 0 || lx < 0 || lz < 0 || lx >= chunksize || lz >= chunksize)
                    {
                        continue;
                    }


                    loadYPosAndThickness(heremapchunk, lx, lz, targetPos, distanceToEdge);


                    // Some deposits may not appear all over cliffs
                    if (Math.Abs(depoCenterPos.Y - targetPos.Y) > MaxYRoughness)
                    {
                        continue;
                    }


                    for (int y = 0; y < hereThickness; y++)
                    {
                        if (targetPos.Y <= 1 || targetPos.Y >= worldheight)
                        {
                            continue;
                        }

                        int index3d = ((targetPos.Y % chunksize) * chunksize + lz) * chunksize + lx;
                        int blockId = chunks[targetPos.Y / chunksize].Blocks[index3d];


                        if (!IgnoreParentTestPerBlock || !parentBlockOk)
                        {
                            parentBlockOk = placeBlockByInBlockId.TryGetValue(blockId, out resolvedPlaceBlock);
                        }

                        if (parentBlockOk && resolvedPlaceBlock.Blocks.Length > 0)
                        {
                            int gradeIndex = Math.Min(resolvedPlaceBlock.Blocks.Length - 1, depositGradeIndex);

                            Block placeblock = resolvedPlaceBlock.Blocks[gradeIndex];

                            if (variant.WithBlockCallback || (WithLastLayerBlockCallback && y == hereThickness - 1))
                            {
                                placeblock.TryPlaceBlockForWorldGen(blockAccessor, targetPos.Copy(), BlockFacing.UP, rand);
                            }
                            else
                            {
                                chunks[targetPos.Y / chunksize].Blocks[index3d] = placeblock.BlockId;
                                //placed++;
                            }

                            if (variant.ChildDeposits != null)
                            {
                                for (int i = 0; i < variant.ChildDeposits.Length; i++)
                                {
                                    float rndVal   = DepositRand.NextFloat();
                                    float quantity = variant.ChildDeposits[i].TriesPerChunk * invChunkAreaSize;

                                    if (quantity > rndVal)
                                    {
                                        if (ShouldPlaceAdjustedForOreMap(variant.ChildDeposits[i], targetPos.X, targetPos.Z, quantity, rndVal))
                                        {
                                            subDepositsToPlace[targetPos.Copy()] = variant.ChildDeposits[i];
                                        }
                                    }
                                }
                            }

                            if (shouldGenSurfaceDeposit)
                            {
                                int   surfaceY = heremapchunk.RainHeightMap[lz * chunksize + lx];
                                int   depth    = surfaceY - targetPos.Y;
                                float chance   = SurfaceBlockChance * Math.Max(0, 1.11f - depth / 9f);
                                if (surfaceY < worldheight && DepositRand.NextFloat() < chance)
                                {
                                    Block belowBlock = Api.World.Blocks[chunks[surfaceY / chunksize].Blocks[((surfaceY % chunksize) * chunksize + lz) * chunksize + lx]];

                                    index3d = (((surfaceY + 1) % chunksize) * chunksize + lz) * chunksize + lx;
                                    if (belowBlock.SideSolid[BlockFacing.UP.Index] && chunks[(surfaceY + 1) / chunksize].Blocks[index3d] == 0)
                                    {
                                        chunks[(surfaceY + 1) / chunksize].Blocks[index3d] = surfaceBlockByInBlockId[blockId].Blocks[0].BlockId;
                                    }
                                }
                            }
                        }

                        targetPos.Y--;
                    }
                }
            }

            //Console.WriteLine("placed {0} blocks", placed);
        }
Example #2
0
        public override void GenDeposit(IBlockAccessor blockAccessor, IServerChunk[] chunks, int chunkX, int chunkZ, BlockPos depoCenterPos, ref Dictionary <BlockPos, DepositVariant> subDepositsToPlace)
        {
            int radius = Math.Min(64, (int)Radius.nextFloat(1, DepositRand));

            if (radius <= 0)
            {
                return;
            }

            // Let's deform that perfect circle a bit (+/- 25%)
            float deform = GameMath.Clamp(DepositRand.NextFloat() - 0.5f, -0.25f, 0.25f);

            radiusX = radius - (int)(radius * deform);
            radiusZ = radius + (int)(radius * deform);


            int baseX = chunkX * chunksize;
            int baseZ = chunkZ * chunksize;


            // No need to caluclate further if this deposit won't be part of this chunk
            if (depoCenterPos.X + radiusX < baseX - 6 || depoCenterPos.Z + radiusZ < baseZ - 6 || depoCenterPos.X - radiusX >= baseX + chunksize + 6 || depoCenterPos.Z - radiusZ >= baseZ + chunksize + 6)
            {
                return;
            }

            IMapChunk heremapchunk = chunks[0].MapChunk;


            // Ok generate
            float th = Thickness.nextFloat(1, DepositRand);
            float depoitThickness = (int)th + (DepositRand.NextFloat() < th - (int)th ? 1 : 0);

            float xRadSqInv = 1f / (radiusX * radiusX);
            float zRadSqInv = 1f / (radiusZ * radiusZ);

            int lx = GameMath.Mod(depoCenterPos.X, chunksize);
            int lz = GameMath.Mod(depoCenterPos.Z, chunksize);
            int distx, distz;

            // No need to go search far beyond chunk boundaries
            int minx = baseX - 6;
            int maxx = baseX + chunksize + 6;
            int minz = baseZ - 6;
            int maxz = baseZ + chunksize + 6;

            minx = GameMath.Clamp(depoCenterPos.X - radiusX, minx, maxx);
            maxx = GameMath.Clamp(depoCenterPos.X + radiusX, minx, maxx);
            minz = GameMath.Clamp(depoCenterPos.Z - radiusZ, minz, maxz);
            maxz = GameMath.Clamp(depoCenterPos.Z + radiusZ, minz, maxz);

            float  invChunkAreaSize = 1f / (chunksize * chunksize);
            double val = 1;

            IList <Block> blocktypes = Api.World.Blocks;

            bool doGravel = DepositRand.NextFloat() > 0.33;

            for (int posx = minx; posx < maxx; posx++)
            {
                targetPos.X = posx;
                lx          = targetPos.X - baseX;
                distx       = posx - depoCenterPos.X;

                float xSq = distx * distx * xRadSqInv;

                for (int posz = minz; posz < maxz; posz++)
                {
                    targetPos.Z = posz;
                    lz          = targetPos.Z - baseZ;
                    distz       = posz - depoCenterPos.Z;

                    // Kinda weird mathematically speaking, but seems to work as a means to distort the perfect circleness of deposits ¯\_(ツ)_/¯
                    // Also not very efficient to use direct perlin noise in here :/
                    // But after ~10 hours of failing (=weird lines of missing deposit material) with a pre-generated 2d distortion map i give up >.>
                    val = 1 - DistortNoiseGen.Noise(targetPos.X / 3.0, targetPos.Z / 3.0) * 1.5 + 0.15;
                    double distanceToEdge = val - (xSq + distz * distz * zRadSqInv);

                    if (distanceToEdge < 0 || lx < 0 || lz < 0 || lx >= chunksize || lz >= chunksize)
                    {
                        continue;
                    }

                    targetPos.Y = heremapchunk.WorldGenTerrainHeightMap[lz * chunksize + lx];

                    // Some deposits may not appear all over cliffs
                    if (Math.Abs(depoCenterPos.Y - targetPos.Y) > MaxYRoughness)
                    {
                        continue;
                    }

                    int rockblockid = heremapchunk.TopRockIdMap[lz * chunksize + lx];

                    Block rockblock = blocktypes[rockblockid];
                    if (!rockblock.Variant.ContainsKey("rock"))
                    {
                        continue;
                    }

                    Block alluvialblock;

                    if (doGravel)
                    {
                        alluvialblock = Api.World.GetBlock(new AssetLocation("gravel-" + rockblock.Variant["rock"]));
                    }
                    else
                    {
                        alluvialblock = Api.World.GetBlock(new AssetLocation("sand-" + rockblock.Variant["rock"]));
                    }


                    for (int y = 0; y < depoitThickness; y++)
                    {
                        if (targetPos.Y <= 1 || targetPos.Y >= worldheight)
                        {
                            continue;
                        }

                        int index3d = ((targetPos.Y % chunksize) * chunksize + lz) * chunksize + lx;
                        int blockId = chunks[targetPos.Y / chunksize].Blocks[index3d];

                        Block block = blocktypes[blockId];

                        if (block.BlockMaterial != EnumBlockMaterial.Soil)
                        {
                            continue;
                        }

                        if (alluvialblock != null)
                        {
                            chunks[targetPos.Y / chunksize].Blocks[index3d] = alluvialblock.BlockId;
                        }

                        targetPos.Y--;
                    }
                }
            }
        }