public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand)
        {
            bool didplace = false;

            if (blockAccessor.GetBlock(pos).Replaceable < 6000)
            {
                return(false);
            }

            BlockPos npos = pos.Copy();

            for (int i = 0; i < 150 + worldGenRand.NextInt(30); i++)
            {
                npos.X = pos.X + worldGenRand.NextInt(11) - 5;
                npos.Y = pos.Y + worldGenRand.NextInt(11) - 5;
                npos.Z = pos.Z + worldGenRand.NextInt(11) - 5;

                if (npos.Y > api.World.SeaLevel - 10 || npos.Y < 25)
                {
                    continue;                                                  // To hot for glowworms
                }
                if (blockAccessor.GetBlock(npos).Replaceable < 6000)
                {
                    continue;
                }

                didplace |= TryGenGlowWorm(blockAccessor, npos, worldGenRand);
            }

            return(didplace);
        }
        private void GenHere(IBlockAccessor blockAccessor, BlockPos pos, LCGRandom worldGenRand)
        {
            int rnd = worldGenRand.NextInt(bases.Length);

            Block placeblock = api.World.GetBlock(CodeWithVariant("type", bases[rnd]));

            blockAccessor.SetBlock(placeblock.Id, pos);

            if (segments[rnd] != null)
            {
                placeblock = api.World.GetBlock(CodeWithVariant("type", segments[rnd]));

                int len = worldGenRand.NextInt(3);
                while (len-- > 0)
                {
                    pos.Down();
                    if (blockAccessor.GetBlock(pos).Replaceable > 6000)
                    {
                        blockAccessor.SetBlock(placeblock.Id, pos);
                    }
                }

                pos.Down();
                placeblock = api.World.GetBlock(CodeWithVariant("type", ends[rnd]));
                if (blockAccessor.GetBlock(pos).Replaceable > 6000)
                {
                    blockAccessor.SetBlock(placeblock.Id, pos);
                }
            }
        }
Example #3
0
        public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand)
        {
            if (!HasBeachyGround(blockAccessor, pos))
            {
                return(false);
            }


            tmpDict["type"] = types[worldGenRand.NextInt(types.Length)];

            if (worldGenRand.NextInt(100) < 8)
            {
                tmpDict["color"] = rarecolors[worldGenRand.NextInt(rarecolors.Length)];
            }
            else
            {
                tmpDict["color"] = colors[worldGenRand.NextInt(colors.Length)];
            }


            Block block = blockAccessor.GetBlock(CodeWithVariants(tmpDict));

            if (block == null)
            {
                return(false);
            }

            if (blockAccessor.GetBlock(pos).IsReplacableBy(this))
            {
                blockAccessor.SetBlock(block.BlockId, pos);
                return(true);
            }

            return(false);
        }
Example #4
0
        internal void LoadRandomPattern()
        {
            NewWePattern = RandomWeatherPattern();
            OldWePattern = RandomWeatherPattern();

            NewWePattern.OnBeginUse();
            OldWePattern.OnBeginUse();

            CurWindPattern = WindPatterns[Rand.NextInt(WindPatterns.Length)];
            CurWindPattern.OnBeginUse();

            CurWeatherEvent = RandomWeatherEvent();
            CurWeatherEvent.OnBeginUse();

            Weight = 1;

            wsServer?.SendWeatherStateUpdate(new WeatherState()
            {
                RegionX         = regionX,
                RegionZ         = regionZ,
                NewPattern      = NewWePattern.State,
                OldPattern      = OldWePattern.State,
                WindPattern     = CurWindPattern.State,
                WeatherEvent    = CurWeatherEvent?.State,
                TransitionDelay = 0,
                Transitioning   = false,
                Weight          = Weight,
                updateInstant   = false,
                LcgCurrentSeed  = Rand.currentSeed,
                LcgMapGenSeed   = Rand.mapGenSeed,
                LcgWorldSeed    = Rand.worldSeed
            });
        }
        public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand)
        {
            if (blockAccessor.GetBlockId(pos) != 0)
            {
                return(false);
            }

            int surfaceY = blockAccessor.GetTerrainMapheightAt(pos);

            if (surfaceY - pos.Y < 30 || pos.Y < 25)
            {
                return(false);
            }

            BlockPos cavepos = getSemiLargeCavePos(blockAccessor, pos);

            if (cavepos == null)
            {
                return(false);
            }

            int dy = 0;

            while (dy < 15 && !blockAccessor.GetBlock(cavepos.X, cavepos.Y + dy, cavepos.Z).SideSolid[BlockFacing.UP.Index])
            {
                dy++;
            }
            if (dy >= 15)
            {
                return(false);
            }
            blockAccessor.SetBlock(this.BlockId, cavepos.AddCopy(0, dy, 0));
            if (EntityClass != null)
            {
                blockAccessor.SpawnBlockEntity(EntityClass, cavepos.AddCopy(0, dy, 0));
            }

            BlockPos tmppos = new BlockPos();
            int      tries  = 55 + worldGenRand.NextInt(55);

            while (tries-- > 0)
            {
                int offX = worldGenRand.NextInt(15) - 7;
                int offY = worldGenRand.NextInt(15) - 7;
                int offZ = worldGenRand.NextInt(15) - 7;

                if (worldGenRand.NextDouble() < 0.4)
                {
                    tryPlaceDecoUp(tmppos.Set(cavepos.X + offX, cavepos.Y + offY, cavepos.Z + offZ), blockAccessor, worldGenRand);
                }
                else
                {
                    tryPlaceDecoDown(tmppos.Set(cavepos.X + offX, cavepos.Y + offY, cavepos.Z + offZ), blockAccessor, worldGenRand);
                }
            }

            return(true);
        }
Example #6
0
        private void OnChunkColumnGen(IServerChunk[] chunks, int chunkX, int chunkZ, ITreeAttribute chunkGenParams = null)
        {
            Dictionary <Vec3i, int> ores = new Dictionary <Vec3i, int>();

            for (int cY = 0; cY < chunks.Length; cY++)
            {
                IServerChunk chunk = chunks[cY];
                if (chunk.Blocks == null)
                {
                    continue;
                }
                for (int x = 0; x < chunksize; x++)
                {
                    for (int y = 0; y < chunksize; y++)
                    {
                        for (int z = 0; z < chunksize; z++)
                        {
                            int block = chunk.Blocks[(y * chunksize + z) * chunksize + x];
                            if (surfaceBlocks.ContainsKey(block) && !ores.ContainsKey(new Vec3i(x, y, z)))
                            {
                                ores.Add(new Vec3i(x, y, z), block);
                            }
                        }
                    }
                }
                foreach (var val in ores)
                {
                    Vec3i vec = val.Key;
                    int   ore = val.Value;
                    if (surfaceBlocks.TryGetValue(ore, out int surface))
                    {
                        for (int y = vec.Y; y < chunksize; y++)
                        {
                            rnd.InitPositionSeed(chunkX * vec.X, chunkZ * vec.Z);
                            if (y < 1 || rnd.NextDouble() > 0.1)
                            {
                                continue;
                            }
                            int dX = rnd.NextInt(chunksize), dZ = rnd.NextInt(chunksize);

                            int block  = chunk.Blocks[(y * chunksize + dZ) * chunksize + dX];
                            int dBlock = chunk.Blocks[((y - 1) * chunksize + dZ) * chunksize + dX];
                            if (bA.GetBlock(dBlock).Fertility > 4 && bA.GetBlock(block).IsReplacableBy(bA.GetBlock(ore)) && !bA.GetBlock(block).IsLiquid())
                            {
                                chunk.Blocks[(y * chunksize + dZ) * chunksize + dX] = surface;
                                bA.ScheduleBlockUpdate(new BlockPos(dX, y, dZ));
                            }
                        }
                    }
                }
            }
        }
        public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldgenRandom)
        {
            var dBlock = blockAccessor.GetBlock(pos.X, pos.Y - 1, pos.Z);

            if (dBlock.Fertility <= 20)
            {
                return(false);
            }

            var climate = blockAccessor.GetClimateAt(pos, EnumGetClimateMode.WorldGenValues);
            int rnd     = worldgenRandom.NextInt(WorldGenConds.Length);

            int len = WorldGenConds.Length;

            for (int i = 0; i < len; i++)
            {
                var conds = WorldGenConds[(i + rnd) % len];
                if (conds.MinTemp <= climate.Temperature && conds.MaxTemp >= climate.Temperature && conds.MinRain <= climate.Rainfall && conds.MaxRain >= climate.Rainfall && worldgenRandom.NextFloat() <= conds.Chance)
                {
                    blockAccessor.SetBlock(BlockId, pos);
                    blockAccessor.SpawnBlockEntity(EntityClass, pos);
                    var be = blockAccessor.GetBlockEntity(pos) as BlockEntityFruitTreeBranch;

                    be.TreeType          = conds.Type;
                    be.InitAfterWorldGen = true;

                    return(true);
                }
            }

            return(false);
        }
        void PlaceTallGrass(int x, int posY, int z, IServerChunk[] chunks, float rainRel, float tempRel, float temp, float forestRel)
        {
            double rndVal = blockLayerConfig.Tallgrass.RndWeight * rnd.NextDouble() + blockLayerConfig.Tallgrass.PerlinWeight * grassDensity.Noise(x, z, -0.5f);

            double extraGrass = Math.Max(0, rainRel * tempRel - 0.25);

            if (rndVal <= GameMath.Clamp(forestRel - extraGrass, 0.05, 0.99) || posY >= mapheight - 1 || posY < 1)
            {
                return;
            }

            int blockId = chunks[posY / chunksize].Blocks[(chunksize * (posY % chunksize) + z) * chunksize + x];

            if (api.World.Blocks[blockId].Fertility <= rnd.NextInt(100))
            {
                return;
            }

            double gheight = Math.Max(0, grassHeight.Noise(x, z) * blockLayerConfig.Tallgrass.BlockCodeByMin.Length - 1);
            int    start   = (int)gheight + (rnd.NextDouble() < gheight ? 1 : 0);

            for (int i = start; i < blockLayerConfig.Tallgrass.BlockCodeByMin.Length; i++)
            {
                TallGrassBlockCodeByMin bcbymin = blockLayerConfig.Tallgrass.BlockCodeByMin[i];

                if (forestRel <= bcbymin.MaxForest && rainRel >= bcbymin.MinRain && temp >= bcbymin.MinTemp)
                {
                    chunks[(posY + 1) / chunksize].Blocks[(chunksize * ((posY + 1) % chunksize) + z) * chunksize + x] = bcbymin.BlockId;
                    return;
                }
            }
        }
        private void tryPlaceDecoUp(BlockPos blockPos, IBlockAccessor blockAccessor, LCGRandom worldgenRand)
        {
            if (blockAccessor.GetBlockId(blockPos) != 0)
            {
                return;
            }

            int tries = 7;

            while (tries-- > 0)
            {
                blockPos.Y++;
                Block block = blockAccessor.GetBlock(blockPos);
                if (block.IsLiquid())
                {
                    return;
                }
                if (block.SideSolid[BlockFacing.DOWN.Index])
                {
                    blockPos.Y--;
                    Block placeblock = DecoBlocksCeiling[worldgenRand.NextInt(DecoBlocksCeiling.Length)];
                    blockAccessor.SetBlock(placeblock.BlockId, blockPos);
                    return;
                }
            }
        }
Example #10
0
        public void Generate(IBlockAccessor blockAccessor, LCGRandom rnd, int posX, int posY, int posZ, int firstBlockId)
        {
            float quantity  = Quantity.nextFloat() + 1;
            int   chunkSize = blockAccessor.ChunkSize;

            Block[] blocks = getBlocks(firstBlockId);
            if (blocks.Length == 0)
            {
                return;
            }

            while (quantity-- > 0)
            {
                if (quantity < 1 && rnd.NextDouble() > quantity)
                {
                    break;
                }

                pos.X = posX + (int)OffsetX.nextFloat();
                pos.Z = posZ + (int)OffsetZ.nextFloat();

                int index = GameMath.Mod((int)BlockCodeIndex.nextFloat(), blocks.Length);

                IServerChunk chunk = (IServerChunk)blockAccessor.GetChunk(pos.X / chunkSize, 0, pos.Z / chunkSize);
                if (chunk == null)
                {
                    break;
                }

                int lx = GameMath.Mod(pos.X, chunkSize);
                int lz = GameMath.Mod(pos.Z, chunkSize);

                if (Placement == EnumBlockPatchPlacement.Underground)
                {
                    pos.Y = rnd.NextInt(Math.Max(1, chunk.MapChunk.WorldGenTerrainHeightMap[lz * blockAccessor.ChunkSize + lx] - 1));
                }
                else
                {
                    pos.Y = chunk.MapChunk.RainHeightMap[lz * blockAccessor.ChunkSize + lx] + 1;

                    if (Math.Abs(pos.Y - posY) > 8 || pos.Y >= blockAccessor.MapSizeY - 1)
                    {
                        continue;
                    }

                    if (Placement == EnumBlockPatchPlacement.UnderWater)
                    {
                        tempPos.Set(pos.X, pos.Y - GameMath.Max(1, MinWaterDepth), pos.Z);
                        Block downBlock = blockAccessor.GetBlock(tempPos);
                        if (downBlock == null || downBlock.LiquidCode != "water")
                        {
                            continue;
                        }
                    }
                }

                blocks[index].TryPlaceBlockForWorldGen(blockAccessor, pos, BlockFacing.UP, rnd);
            }
        }
Example #11
0
        public void Init(ICoreServerAPI api, RockStrataConfig rockstrata, LCGRandom rnd, int i)
        {
            List <Block> blocks = new List <Block>();

            for (int j = 0; j < blockCodes.Length; j++)
            {
                AssetLocation code = blockCodes[j];

                if (code.Path.Contains("{rocktype}"))
                {
                    if (BlocksByRockType == null)
                    {
                        BlocksByRockType = new Dictionary <int, Block[]>();
                    }

                    for (int k = 0; k < rockstrata.Variants.Length; k++)
                    {
                        string        rocktype      = rockstrata.Variants[k].BlockCode.Path.Split('-')[1];
                        AssetLocation rocktypedCode = code.CopyWithPath(code.Path.Replace("{rocktype}", rocktype));

                        Block rockBlock = api.World.GetBlock(rockstrata.Variants[k].BlockCode);

                        if (rockBlock != null)
                        {
                            BlocksByRockType[rockBlock.BlockId] = new Block[] { api.World.GetBlock(rocktypedCode) };
                        }
                    }
                }
                else
                {
                    Block block = api.World.GetBlock(code);
                    if (block != null)
                    {
                        blocks.Add(block);
                    }
                    else
                    {
                        api.World.Logger.Warning("Block patch Nr. {0}: Unable to resolve block with code {1}. Will ignore.", i, code);
                    }
                }
            }

            Blocks = blocks.ToArray();

            if (BlockCodeIndex == null)
            {
                BlockCodeIndex = NatFloat.createUniform(0, Blocks.Length);
            }

            if (RandomMapCodePool != null)
            {
                int index = rnd.NextInt(RandomMapCodePool.Length);
                MapCode = RandomMapCodePool[index];
            }
        }
Example #12
0
        private void GenRareColorPatch(IBlockAccessor blockAccessor, BlockPos pos, Block block, LCGRandom worldGenRand)
        {
            int      cnt   = 2 + worldGenRand.NextInt(6);
            int      tries = 30;
            BlockPos npos  = pos.Copy();

            while (cnt > 0 && tries-- > 0)
            {
                npos.Set(pos).Add(worldGenRand.NextInt(5) - 2, 0, worldGenRand.NextInt(5) - 2);
                npos.Y = blockAccessor.GetTerrainMapheightAt(npos) + 1;

                Block nblock = blockAccessor.GetBlock(npos);

                if ((nblock.IsReplacableBy(block) || nblock is BlockLupine) && CanPlantStay(blockAccessor, npos))
                {
                    blockAccessor.SetBlock(block.BlockId, npos);
                    cnt--;
                }
            }
        }
Example #13
0
        public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand)
        {
            bool placed = base.TryPlaceBlockForWorldGen(blockAccessor, pos, onBlockFace, worldGenRand);

            if (!placed)
            {
                return(false);
            }

            double rnd = worldGenRand.NextDouble();

            if (rnd < 1 / 300.0)
            {
                GenRareColorPatch(blockAccessor, pos, rareVariants[worldGenRand.NextInt(rareVariants.Length)], worldGenRand);
            }
            else if (rnd < 1 / 120.0)
            {
                GenRareColorPatch(blockAccessor, pos, uncommonVariants[worldGenRand.NextInt(uncommonVariants.Length)], worldGenRand);
            }

            return(true);
        }
        public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand)
        {
            bool didplace = false;

            if (blockAccessor.GetBlock(pos).Replaceable < 6000)
            {
                return(false);
            }

            pos = pos.Copy();
            for (int i = 0; i < 5 + worldGenRand.NextInt(25); i++)
            {
                if (pos.Y < 15)
                {
                    continue;             // To hot for stalactites
                }
                didplace |= TryGenStalag(blockAccessor, pos, worldGenRand.NextInt(4), worldGenRand);
                pos.X    += worldGenRand.NextInt(9) - 4;
                pos.Y    += worldGenRand.NextInt(3) - 1;
                pos.Z    += worldGenRand.NextInt(9) - 4;
            }

            return(didplace);
        }
Example #15
0
        /// <summary>
        /// Performs a Fisher-Yates shuffle in linear time or O(n)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="rand"></param>
        /// <param name="array"></param>
        public static T[] Shuffle <T>(this T[] array, LCGRandom rand)
        {
            int n = array.Length;        // The number of items left to shuffle (loop invariant).

            while (n > 1)
            {
                int k = rand.NextInt(n); // 0 <= k < n.
                n--;                     // n is now the last pertinent index;
                T temp = array[n];       // swap array[n] with array[k] (does nothing if k == n).
                array[n] = array[k];
                array[k] = temp;
            }

            return(array);
        }
        private void GrowDownFrom(IBlockAccessor blockAccessor, BlockPos pos, string rocktype, int thickOff, LCGRandom worldGenRand)
        {
            for (int i = thicknessIndex[Thickness] + thickOff + worldGenRand.NextInt(2); i < Thicknesses.Length; i++)
            {
                Block stalagBlock = GetBlock(api.World, rocktype, Thicknesses[i]);
                if (stalagBlock == null)
                {
                    continue;
                }

                Block block = blockAccessor.GetBlock(pos);
                if (!block.IsLiquid() && block.Replaceable >= 6000)
                {
                    blockAccessor.SetBlock(stalagBlock.BlockId, pos);
                }
                else
                {
                    break;
                }
                pos.Y--;
            }
        }
        private void GenPatches(IBlockAccessor blockAccessor, BlockPos pos, float forestNess, EnumTreeType treetype, LCGRandom rnd)
        {
            var bpc         = genPatchesSystem.bpc;
            int radius      = 5;
            int worldheight = blockAccessor.MapSizeY;

            int cnt = underTreePatches?.Count ?? 0;

            for (int i = 0; i < cnt; i++)
            {
                BlockPatch bPatch = underTreePatches[i];
                if (bPatch.TreeType != EnumTreeType.Any && bPatch.TreeType != treetype)
                {
                    continue;
                }

                float chance = 0.003f * forestNess * bPatch.Chance * bpc.ChanceMultiplier.nextFloat();

                //if (bPatch.blockCodes[0].Path.Contains("mushroom")) chance *= 20; - for debugging

                while (chance-- > rnd.NextDouble())
                {
                    int dx = rnd.NextInt(2 * radius) - radius;
                    int dz = rnd.NextInt(2 * radius) - radius;

                    tmpPos.Set(pos.X + dx, 0, pos.Z + dz);

                    int y = blockAccessor.GetTerrainMapheightAt(tmpPos);
                    if (y <= 0 || y >= worldheight - 8)
                    {
                        continue;
                    }

                    tmpPos.Y = y;

                    var climate = blockAccessor.GetClimateAt(tmpPos, EnumGetClimateMode.WorldGenValues);
                    if (climate == null)
                    {
                        continue;
                    }

                    if (bpc.IsPatchSuitableUnderTree(bPatch, worldheight, climate, y))
                    {
                        int regionX = pos.X / blockAccessor.RegionSize;
                        int regionZ = pos.Z / blockAccessor.RegionSize;
                        if (bPatch.MapCode != null && rnd.NextInt(255) > genPatchesSystem.GetPatchDensity(bPatch.MapCode, tmpPos.X, tmpPos.Z, blockAccessor.GetMapRegion(regionX, regionZ)))
                        {
                            continue;
                        }

                        int  firstBlockId = 0;
                        bool found        = true;

                        if (bPatch.BlocksByRockType != null)
                        {
                            found = false;
                            int dy = 1;
                            while (dy < 5 && y - dy > 0)
                            {
                                string lastCodePart = blockAccessor.GetBlock(tmpPos.X, y - dy, tmpPos.Z).LastCodePart();
                                if (genPatchesSystem.RockBlockIdsByType.TryGetValue(lastCodePart, out firstBlockId))
                                {
                                    found = true; break;
                                }
                                dy++;
                            }
                        }

                        if (found)
                        {
                            bPatch.Generate(blockAccessor, rnd, tmpPos.X, tmpPos.Y, tmpPos.Z, firstBlockId);
                        }
                    }
                }
            }

            cnt = onTreePatches?.Count ?? 0;
            for (int i = 0; i < cnt; i++)
            {
                BlockPatch blockPatch = onTreePatches[i];

                float chance = 3 * forestNess * blockPatch.Chance * bpc.ChanceMultiplier.nextFloat();

                while (chance-- > rnd.NextDouble())
                {
                    int dx = 1 - rnd.NextInt(2) * 2;
                    int dy = rnd.NextInt(5);
                    int dz = 1 - rnd.NextInt(2) * 2;

                    tmpPos.Set(pos.X + dx, pos.Y + dy, pos.Z + dz);

                    var block = api.GetBlock(tmpPos);
                    if (block.Id != 0)
                    {
                        continue;
                    }
                    BlockFacing facing = null;

                    for (int j = 0; j < 4; j++)
                    {
                        var f      = BlockFacing.HORIZONTALS[j];
                        var nblock = api.GetBlock(tmpPos.X + f.Normali.X, tmpPos.Y, tmpPos.Z + f.Normali.Z);
                        if (nblock is BlockLog && nblock.Variant["type"] != "resin")
                        {
                            facing = f;
                            break;
                        }
                    }
                    if (facing == null)
                    {
                        break;
                    }

                    var climate = blockAccessor.GetClimateAt(tmpPos, EnumGetClimateMode.WorldGenValues);
                    if (climate == null)
                    {
                        continue;
                    }

                    if (bpc.IsPatchSuitableUnderTree(blockPatch, worldheight, climate, tmpPos.Y))
                    {
                        int regionX = pos.X / blockAccessor.RegionSize;
                        int regionZ = pos.Z / blockAccessor.RegionSize;
                        if (blockPatch.MapCode != null && rnd.NextInt(255) > genPatchesSystem.GetPatchDensity(blockPatch.MapCode, tmpPos.X, tmpPos.Z, blockAccessor.GetMapRegion(regionX, regionZ)))
                        {
                            continue;
                        }

                        int index = rnd.NextInt(blockPatch.Blocks.Length);
                        blockPatch.Blocks[index].TryPlaceBlockForWorldGen(blockAccessor, tmpPos, facing, rnd);
                    }
                }
            }
        }
Example #18
0
        public void InitWorldGen()
        {
            LoadGlobalConfig(api);

            IAsset           asset      = api.Assets.Get("worldgen/rockstrata.json");
            RockStrataConfig rockstrata = asset.ToObject <RockStrataConfig>();

            asset            = api.Assets.Get("worldgen/blocklayers.json");
            blockLayerConfig = asset.ToObject <BlockLayerConfig>();
            blockLayerConfig.ResolveBlockIds(api, rockstrata);

            rnd          = new LCGRandom(api.WorldManager.Seed);
            grassDensity = new ClampedSimplexNoise(new double[] { 4 }, new double[] { 0.5 }, rnd.NextInt());
            grassHeight  = new ClampedSimplexNoise(new double[] { 1.5 }, new double[] { 0.5 }, rnd.NextInt());

            mapheight = api.WorldManager.MapSizeY;
        }
        public bool TryGenerate(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos pos, int climateUpLeft, int climateUpRight, int climateBotLeft, int climateBotRight, DidGenerate didGenerateStructure)
        {
            this.climateUpLeft   = climateUpLeft;
            this.climateUpRight  = climateUpRight;
            this.climateBotLeft  = climateBotLeft;
            this.climateBotRight = climateBotRight;

            float    cnt         = QuantityStructures.nextFloat();
            int      minQuantity = (int)cnt;
            BlockPos schemPos    = pos.Copy();
            Cuboidi  location    = new Cuboidi();

            rand.InitPositionSeed(pos.X, pos.Z);

            List <GeneratableStructure> generatables = new List <GeneratableStructure>();

            while (cnt-- > 0)
            {
                if (cnt < 1 && rand.NextDouble() > cnt)
                {
                    break;
                }

                int tries = 30;
                while (tries-- > 0)
                {
                    schemPos.Set(pos);
                    schemPos.Add(rand.NextInt(50) - 25, 0, rand.NextInt(50) - 25);
                    schemPos.Y = blockAccessor.GetTerrainMapheightAt(schemPos);

                    double           rndVal = rand.NextDouble() * totalWeight;
                    int              i      = 0;
                    VillageSchematic schem  = null;
                    while (rndVal > 0)
                    {
                        schem   = Schematics[i++];
                        rndVal -= schem.Weight;
                    }
                    BlockSchematicStructure struc = GetGeneratableStructure(schem, blockAccessor, worldForCollectibleResolve, schemPos);

                    if (struc != null)
                    {
                        location.Set(schemPos.X, schemPos.Y, schemPos.Z, schemPos.X + struc.SizeX, schemPos.Y + struc.SizeY, schemPos.Z + struc.SizeZ);
                        bool intersect = false;
                        for (int k = 0; k < generatables.Count; k++)
                        {
                            if (location.IntersectsOrTouches(generatables[k].location))
                            {
                                intersect = true;
                                break;
                            }
                        }

                        if (!intersect)
                        {
                            generatables.Add(new GeneratableStructure()
                            {
                                struc = struc, pos = schemPos.Copy(), location = location.Clone()
                            });
                        }
                        break;
                    }
                }
            }

            if (generatables.Count >= minQuantity)
            {
                foreach (var val in generatables)
                {
                    val.struc.PlaceRespectingBlockLayers(blockAccessor, worldForCollectibleResolve, val.pos, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight, replaceblockids);
                    didGenerateStructure(val.location, val.struc);
                }
            }

            return(true);
        }
        internal bool TryGenerateRuinAtSurface(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos pos)
        {
            int num    = rand.NextInt(schematicDatas.Length);
            int orient = rand.NextInt(4);
            BlockSchematicStructure schematic = schematicDatas[num][orient];


            int wdthalf = (int)Math.Ceiling(schematic.SizeX / 2f);
            int lenhalf = (int)Math.Ceiling(schematic.SizeZ / 2f);

            int wdt = schematic.SizeX;
            int len = schematic.SizeZ;


            tmpPos.Set(pos.X + wdthalf, 0, pos.Z + lenhalf);
            int centerY = blockAccessor.GetTerrainMapheightAt(pos);

            // Probe all 4 corners + center if they either touch the surface or are sightly below ground

            tmpPos.Set(pos.X, 0, pos.Z);
            int topLeftY = blockAccessor.GetTerrainMapheightAt(tmpPos);

            tmpPos.Set(pos.X + wdt, 0, pos.Z);
            int topRightY = blockAccessor.GetTerrainMapheightAt(tmpPos);

            tmpPos.Set(pos.X, 0, pos.Z + len);
            int botLeftY = blockAccessor.GetTerrainMapheightAt(tmpPos);

            tmpPos.Set(pos.X + wdt, 0, pos.Z + len);
            int botRightY = blockAccessor.GetTerrainMapheightAt(tmpPos);


            int maxY = GameMath.Max(centerY, topLeftY, topRightY, botLeftY, botRightY);
            int minY = GameMath.Min(centerY, topLeftY, topRightY, botLeftY, botRightY);
            int diff = Math.Abs(maxY - minY);

            if (diff > 3)
            {
                return(false);
            }

            pos.Y = minY;


            // Ensure not deeply submerged in water

            tmpPos.Set(pos.X, pos.Y + 1 + OffsetY, pos.Z);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(false);
            }

            tmpPos.Set(pos.X + wdt, pos.Y + 1 + OffsetY, pos.Z);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(false);
            }

            tmpPos.Set(pos.X, pos.Y + 1 + OffsetY, pos.Z + len);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(false);
            }

            tmpPos.Set(pos.X + wdt, pos.Y + 1 + OffsetY, pos.Z + len);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(false);
            }


            pos.Y--;

            if (!satisfiesMinDistance(pos, worldForCollectibleResolve))
            {
                return(false);
            }
            if (isStructureAt(pos, worldForCollectibleResolve))
            {
                return(false);
            }

            LastPlacedSchematicLocation.Set(pos.X, pos.Y, pos.Z, pos.X + schematic.SizeX, pos.Y + schematic.SizeY, pos.Z + schematic.SizeZ);
            LastPlacedSchematic = schematic;
            schematic.PlaceRespectingBlockLayers(blockAccessor, worldForCollectibleResolve, pos, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight, replaceblockids);

            return(true);
        }
Example #21
0
        private void OnChunkColumnGen(IServerChunk[] chunks, int chunkX, int chunkZ, ITreeAttribute chunkGenParams = null)
        {
            rand.InitPositionSeed(chunkX, chunkZ);

            ushort[] heightmap = chunks[0].MapChunk.RainHeightMap;

            IntDataMap2D climateMap      = chunks[0].MapChunk.MapRegion.ClimateMap;
            int          regionChunkSize = api.WorldManager.RegionSize / chunksize;
            float        fac             = (float)climateMap.InnerSize / regionChunkSize;
            int          rlX             = chunkX % regionChunkSize;
            int          rlZ             = chunkZ % regionChunkSize;

            climateUpLeft   = climateMap.GetUnpaddedInt((int)(rlX * fac), (int)(rlZ * fac));
            climateUpRight  = climateMap.GetUnpaddedInt((int)(rlX * fac + fac), (int)(rlZ * fac));
            climateBotLeft  = climateMap.GetUnpaddedInt((int)(rlX * fac), (int)(rlZ * fac + fac));
            climateBotRight = climateMap.GetUnpaddedInt((int)(rlX * fac + fac), (int)(rlZ * fac + fac));

            int climateMid = GameMath.BiLerpRgbColor(0.5f, 0.5f, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);

            // 16-23 bits = Red = temperature
            // 8-15 bits = Green = rain
            // 0-7 bits = Blue = humidity

            int rain     = (climateMid >> 8) & 0xff;
            int humidity = climateMid & 0xff;
            int temp     = (climateMid >> 16) & 0xff;

            // Lake density at chunk center
            float pondDensity = 4 * (rain + humidity) / 255f;

            float sealeveltemp = TerraGenConfig.GetScaledAdjustedTemperatureFloat(temp, 0);

            // Less lakes where its below -5 degrees
            pondDensity -= Math.Max(0, 5 - sealeveltemp);

            float maxTries = pondDensity * 10;

            int dx, dz;

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


            while (maxTries-- > 0)
            {
                if (maxTries < 1 && rand.NextDouble() > maxTries)
                {
                    break;
                }

                dx = rand.NextInt(chunksize);
                dz = rand.NextInt(chunksize);

                pondYPos = heightmap[dz * chunksize + dx] + 1;
                if (pondYPos <= 0 || pondYPos >= mapheight - 1)
                {
                    return;
                }

                TryPlacePondAt(dx, pondYPos, dz, chunkX, chunkZ);
            }

            maxTries = 600;
            while (maxTries-- > 0)
            {
                if (maxTries < 1 && rand.NextDouble() > maxTries)
                {
                    break;
                }

                dx = rand.NextInt(chunksize);
                dz = rand.NextInt(chunksize);

                pondYPos = (int)(rand.NextDouble() * heightmap[dz * chunksize + dx]);
                if (pondYPos <= 0 || pondYPos >= mapheight - 1)
                {
                    return;
                }

                int chunkY  = pondYPos / chunksize;
                int dy      = pondYPos % chunksize;
                int blockID = chunks[chunkY].Blocks[(dy * chunksize + dz) * chunksize + dx];

                while (blockID == 0 && pondYPos > 20)
                {
                    pondYPos--;

                    chunkY  = pondYPos / chunksize;
                    dy      = pondYPos % chunksize;
                    blockID = chunks[chunkY].Blocks[(dy * chunksize + dz) * chunksize + dx];

                    if (blockID != 0)
                    {
                        //blockAccessor.SetBlock(63, new BlockPos(dx + baseX, pondYPos, dz + baseZ));
                        TryPlacePondAt(dx, pondYPos, dz, chunkX, chunkZ);
                    }
                }
            }
        }
Example #22
0
        public override bool TryPlaceBlockForWorldGen(IBlockAccessor blAcc, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldgenRand)
        {
            int   cnt          = 2 + worldgenRand.NextInt(25);
            float depth        = GameMath.Sqrt(GameMath.Sqrt(cnt));
            float craterRadius = GameMath.Sqrt(cnt) * 1.25f;

            // Look for even or downwards curved ground
            if (pos.Y > 250 ||
                !IsSolid(blAcc, pos.X, pos.Y - 3, pos.Z) ||
                !IsSolid(blAcc, pos.X, pos.Y - (int)depth, pos.Z) ||
                !IsSolid(blAcc, pos.X + (int)craterRadius, pos.Y - 1, pos.Z) ||
                !IsSolid(blAcc, pos.X - (int)craterRadius, pos.Y - 1, pos.Z) ||
                !IsSolid(blAcc, pos.X, pos.Y - 1, pos.Z - (int)craterRadius) ||
                !IsSolid(blAcc, pos.X, pos.Y - 1, pos.Z + (int)craterRadius)
                )
            {
                return(false);
            }

            int y1 = blAcc.GetTerrainMapheightAt(tmpPos.Set(pos.X - 5, pos.Y, pos.Z));
            int y2 = blAcc.GetTerrainMapheightAt(tmpPos.Set(pos.X + 5, pos.Y, pos.Z));
            int y3 = blAcc.GetTerrainMapheightAt(tmpPos.Set(pos.X - 0, pos.Y, pos.Z + 5));
            int y4 = blAcc.GetTerrainMapheightAt(tmpPos.Set(pos.X - 0, pos.Y, pos.Z - 5));

            if ((GameMath.Max(y1, y2, y3, y4) - GameMath.Min(y1, y2, y3, y4)) > 4)
            {
                return(false);
            }



            tmpPos = tmpPos.Set(pos.X, pos.Y - (int)depth - 2, pos.Z);
            while (cnt-- > 0)
            {
                tmpPos.X += worldgenRand.NextInt(3) == 0 ? (worldgenRand.NextInt(3) - 1) : 0;
                tmpPos.Y += worldgenRand.NextInt(8) == 0 ? (worldgenRand.NextInt(3) - 1) : 0;
                tmpPos.Z += worldgenRand.NextInt(3) == 0 ? (worldgenRand.NextInt(3) - 1) : 0;

                blAcc.SetBlock(this.BlockId, tmpPos);
            }



            int sueviteBlockId      = api.World.GetBlock(new AssetLocation("rock-suevite")).BlockId;
            int fragmentBlockId     = api.World.GetBlock(new AssetLocation("loosestones-meteorite-iron-free")).BlockId;
            int looseSueviteBlockId = api.World.GetBlock(new AssetLocation("loosestones-suevite-free")).BlockId;

            float impactRockRadius = craterRadius * 1.2f;
            int   range            = (int)Math.Ceiling(impactRockRadius);
            int   chunksize        = api.World.BlockAccessor.ChunkSize;
            Vec2i vecTmp           = new Vec2i();

            // 1. Generate a basin of suevite and lower terrain
            for (int dx = -range; dx <= range; dx++)
            {
                for (int dz = -range; dz <= range; dz++)
                {
                    float distImpactRockEdge = (dx * dx + dz * dz) / (impactRockRadius * impactRockRadius);
                    if (distImpactRockEdge > 1)
                    {
                        continue;
                    }

                    tmpPos.X = pos.X + dx;
                    tmpPos.Z = pos.Z + dz;
                    int surfaceY = blAcc.GetTerrainMapheightAt(tmpPos);
                    tmpPos.Y = surfaceY - (int)depth;

                    vecTmp.X = tmpPos.X / chunksize;
                    vecTmp.Y = tmpPos.Z / chunksize;
                    IMapChunk mapchunk = blAcc.GetMapChunk(vecTmp);


                    float q = 3 * Math.Max(0, 2 * (1 - distImpactRockEdge) - 0.2f);
                    tmpPos.Y -= (int)q + 1;


                    while (q > 0)
                    {
                        if (q < 1 && worldgenRand.NextDouble() > q)
                        {
                            break;
                        }

                        Block block = blAcc.GetBlock(tmpPos);

                        if (block != this && block.BlockMaterial == EnumBlockMaterial.Stone)
                        {
                            blAcc.SetBlock(sueviteBlockId, tmpPos);
                        }
                        q--;
                        tmpPos.Y++;
                    }

                    float distToCraterEdge = (dx * dx + dz * dz) / (craterRadius * craterRadius) + (float)worldgenRand.NextDouble() * 0.1f;
                    if (distToCraterEdge > 1)
                    {
                        continue;
                    }

                    q = depth * (1 - distToCraterEdge);

                    tmpPos.Y = surfaceY;
                    Block surfaceblock      = blAcc.GetBlock(tmpPos);
                    Block abovesurfaceblock = blAcc.GetBlock(tmpPos.X, tmpPos.Y + 1, tmpPos.Z);

                    for (int i = -1; i <= (int)q; i++)
                    {
                        tmpPos.Y = surfaceY - i;
                        int id = i == (int)q ? surfaceblock.BlockId : 0;

                        Block bblock = blAcc.GetBlock(tmpPos);
                        if (!bblock.IsLiquid())
                        {
                            blAcc.SetBlock(id, tmpPos);
                        }
                    }

                    mapchunk.WorldGenTerrainHeightMap[(tmpPos.Z % chunksize) * chunksize + (tmpPos.X % chunksize)] -= (ushort)q;

                    tmpPos.Y = blAcc.GetTerrainMapheightAt(tmpPos) + 1;

                    blAcc.SetBlock(abovesurfaceblock.BlockId, tmpPos);
                }
            }

            int quantityFragments = 0;

            if (worldgenRand.NextInt(10) == 0)
            {
                quantityFragments = worldgenRand.NextInt(10);
            }
            else if (worldgenRand.NextInt(5) == 0)
            {
                quantityFragments = worldgenRand.NextInt(5);
            }

            while (quantityFragments-- > 0)
            {
                tmpPos.Set(
                    pos.X + (worldgenRand.NextInt(11) + worldgenRand.NextInt(11)) / 2 - 5,
                    0,
                    pos.Z + (worldgenRand.NextInt(11) + worldgenRand.NextInt(11)) / 2 - 5
                    );
                tmpPos.Y = blAcc.GetTerrainMapheightAt(tmpPos) + 1;

                if (!blAcc.GetBlock(tmpPos.X, tmpPos.Y - 1, tmpPos.Z).SideSolid[BlockFacing.UP.Index])
                {
                    continue;
                }

                if (worldgenRand.NextDouble() < 0.3)
                {
                    blAcc.SetBlock(fragmentBlockId, tmpPos);
                }
                else
                {
                    blAcc.SetBlock(looseSueviteBlockId, tmpPos);
                }
            }

            //blAcc.SetBlock(61, pos.AddCopy(0, 20, 0));


            return(true);
        }
Example #23
0
        private void DoGenStructures(IMapRegion region, int chunkX, int chunkZ, bool postPass, ITreeAttribute chunkGenParams = null)
        {
            BlockPos pos = new BlockPos();

            ITreeAttribute chanceModTree      = null;
            ITreeAttribute maxQuantityModTree = null;

            if (chunkGenParams?["structureChanceModifier"] != null)
            {
                chanceModTree = chunkGenParams["structureChanceModifier"] as TreeAttribute;
            }
            if (chunkGenParams?["structureMaxCount"] != null)
            {
                maxQuantityModTree = chunkGenParams["structureMaxCount"] as TreeAttribute;
            }


            strucRand.InitPositionSeed(chunkX, chunkZ);

            scfg.Structures.Shuffle(strucRand);

            for (int i = 0; i < scfg.Structures.Length; i++)
            {
                WorldGenStructure struc = scfg.Structures[i];
                if (struc.PostPass != postPass)
                {
                    continue;
                }

                float chance     = struc.Chance * scfg.ChanceMultiplier;
                int   toGenerate = 9999;
                if (chanceModTree != null)
                {
                    chance *= chanceModTree.GetFloat(struc.Code, 0);
                }

                if (maxQuantityModTree != null)
                {
                    toGenerate = maxQuantityModTree.GetInt(struc.Code, 9999);
                }


                while (chance-- > strucRand.NextDouble() && toGenerate > 0)
                {
                    int dx       = strucRand.NextInt(chunksize);
                    int dz       = strucRand.NextInt(chunksize);
                    int ySurface = heightmap[dz * chunksize + dx];
                    if (ySurface <= 0 || ySurface >= worldheight - 15)
                    {
                        continue;
                    }

                    if (struc.Placement == EnumStructurePlacement.Underground)
                    {
                        if (struc.Depth != null)
                        {
                            pos.Set(chunkX * chunksize + dx, ySurface - (int)struc.Depth.nextFloat(1, strucRand), chunkZ * chunksize + dz);
                        }
                        else
                        {
                            pos.Set(chunkX * chunksize + dx, 8 + strucRand.NextInt(ySurface - 8 - 5), chunkZ * chunksize + dz);
                        }
                    }
                    else
                    {
                        pos.Set(chunkX * chunksize + dx, ySurface, chunkZ * chunksize + dz);
                    }

                    if (struc.TryGenerate(worldgenBlockAccessor, api.World, pos, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight))
                    {
                        Cuboidi loc = struc.LastPlacedSchematicLocation;

                        string code = struc.Code + (struc.LastPlacedSchematic == null ? "" : "/" + struc.LastPlacedSchematic.FromFileName);

                        region.GeneratedStructures.Add(new GeneratedStructure()
                        {
                            Code = code, Group = struc.Group, Location = loc.Clone()
                        });
                        region.DirtyForSaving = true;

                        if (struc.BuildProtected)
                        {
                            api.World.Claims.Add(new LandClaim()
                            {
                                Areas = new List <Cuboidi>()
                                {
                                    loc.Clone()
                                },
                                Description        = struc.BuildProtectionDesc,
                                ProtectionLevel    = 10,
                                LastKnownOwnerName = struc.BuildProtectionName,
                                AllowUse           = true
                            });
                        }

                        toGenerate--;
                    }
                }
            }
        }
Example #24
0
        void genPatches(int chunkX, int chunkZ, bool postPass)
        {
            int   dx, dz, x, z;
            Block block;

            for (int i = 0; i < bpc.Patches.Length; i++)
            {
                BlockPatch blockPatch = bpc.Patches[i];
                if (blockPatch.PostPass != postPass)
                {
                    continue;
                }

                float chance = blockPatch.Chance * bpc.ChanceMultiplier.nextFloat();

                while (chance-- > rnd.NextDouble())
                {
                    dx = rnd.NextInt(chunksize);
                    dz = rnd.NextInt(chunksize);
                    x  = dx + chunkX * chunksize;
                    z  = dz + chunkZ * chunksize;

                    int y = heightmap[dz * chunksize + dx];
                    if (y <= 0 || y >= worldheight - 15)
                    {
                        continue;
                    }

                    tmpPos.Set(x, y, z);
                    block = blockAccessor.GetBlock(tmpPos);

                    // Place according to forest value
                    float forestRel = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)dx / chunksize, (float)dz / chunksize) / 255f;
                    forestRel = GameMath.Clamp(forestRel + forestMod, 0, 1);

                    int climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);

                    if (bpc.IsPatchSuitableAt(blockPatch, block, api.WorldManager, climate, y, forestRel))
                    {
                        int  firstBlockId = 0;
                        bool found        = true;

                        if (blockPatch.BlocksByRockType != null)
                        {
                            found = false;
                            int dy = 1;
                            while (dy < 5 && y - dy > 0)
                            {
                                string lastCodePart = blockAccessor.GetBlock(x, y - dy, z).LastCodePart();
                                if (RockBlockIdsByType.TryGetValue(lastCodePart, out firstBlockId))
                                {
                                    found = true; break;
                                }
                                dy++;
                            }
                        }

                        if (found)
                        {
                            blockPatch.Generate(blockAccessor, rnd, x, y, z, firstBlockId);
                        }
                    }
                }
            }
        }
Example #25
0
        private void CarveTunnel(IServerChunk[] chunks, int chunkX, int chunkZ, double posX, double posY, double posZ, float horAngle, float vertAngle, float horizontalSize, float verticalSize, int currentIteration, int maxIterations, int branchLevel, bool extraBranchy = false, float curviness = 0.1f, bool largeNearLavaLayer = false)
        {
            blockId = airBlockId;

            ushort[] terrainheightmap = chunks[0].MapChunk.WorldGenTerrainHeightMap;
            ushort[] rainheightmap    = chunks[0].MapChunk.RainHeightMap;

            float horAngleChange     = 0;
            float vertAngleChange    = 0;
            float horRadiusGain      = 0;
            float horRadiusLoss      = 0;
            float horRadiusGainAccum = 0;
            float horRadiusLossAccum = 0;

            float verHeightGain      = 0;
            float verHeightLoss      = 0;
            float verHeightGainAccum = 0;
            float verHeightLossAccum = 0;

            float sizeChangeSpeedAccum = 0.15f;
            float sizeChangeSpeedGain  = 0f;

            float relPos;

            int branchRand = (branchLevel + 1) * (extraBranchy ? 12 : 25);

            while (currentIteration++ < maxIterations)
            {
                relPos = (float)currentIteration / maxIterations;

                float horRadius = 1.5f + GameMath.FastSin(relPos * GameMath.PI) * horizontalSize + horRadiusGainAccum;
                horRadius = Math.Min(horRadius, Math.Max(1, horRadius - horRadiusLossAccum));

                float vertRadius = 1.5f + GameMath.FastSin(relPos * GameMath.PI) * (verticalSize + horRadiusLossAccum / 4) + verHeightGainAccum; // - horRadiusGainAccum / 2
                vertRadius = Math.Min(vertRadius, Math.Max(0.6f, vertRadius - verHeightLossAccum));

                float advanceHor = GameMath.FastCos(vertAngle);
                float advanceVer = GameMath.FastSin(vertAngle);

                // Caves get bigger near y=12
                if (largeNearLavaLayer)
                {
                    horRadius  *= 1 + Math.Max(0, (10 - (float)Math.Abs(posY - 12)) / 10f);
                    vertRadius *= 1 + Math.Max(0, (10 - (float)Math.Abs(posY - 12)) / 10f);
                }

                if (vertRadius < 1)
                {
                    vertAngle *= 0.1f;
                }

                posX += GameMath.FastCos(horAngle) * advanceHor;
                posY += GameMath.Clamp(advanceVer, -vertRadius, vertRadius);
                posZ += GameMath.FastSin(horAngle) * advanceHor;

                vertAngle *= 0.8f;



                if (caveRand.NextInt(80) == 0)
                {
                    sizeChangeSpeedGain = (caveRand.NextFloat() * caveRand.NextFloat()) / 2;
                }

                int rnd = caveRand.NextInt(10000); // Calls to caveRand are not too cheap, so lets just use one for all those random variation changes
                // 1/330 * 10k = 30
                // 1/130 * 10k = 76
                // 1/100 * 10k = 100
                // 1/120 * 10k = 83
                // 1/800 * 10k = 12

                // Rarely change direction
                if ((rnd -= 30) <= 0)
                {
                    horAngle = caveRand.NextFloat() * GameMath.TWOPI;
                }
                else
                // Rarely change direction somewhat
                if ((rnd -= 76) <= 0)
                {
                    horAngle += caveRand.NextFloat() * GameMath.PI - GameMath.PIHALF;
                }
                else
                // Rarely go pretty wide
                if ((rnd -= 60) <= 0)
                {
                    horRadiusGain = caveRand.NextFloat() * caveRand.NextFloat() * 3.5f;
                }
                else
                // Rarely go thin
                if ((rnd -= 60) <= 0)
                {
                    horRadiusLoss = caveRand.NextFloat() * caveRand.NextFloat() * 10;
                }
                else
                // Rarely go flat
                if ((rnd -= 50) <= 0)
                {
                    if (posY < TerraGenConfig.seaLevel - 10)
                    {
                        verHeightLoss = caveRand.NextFloat() * caveRand.NextFloat() * 12;
                        horRadiusGain = Math.Max(horRadiusGain, caveRand.NextFloat() * caveRand.NextFloat() * 3);
                    }
                }
                else
                // Very rarely go really wide
                if ((rnd -= 9) <= 0)
                {
                    if (posY < TerraGenConfig.seaLevel - 20)
                    {
                        horRadiusGain = 1 + caveRand.NextFloat() * caveRand.NextFloat() * 5f;
                    }
                }
                else
                // Very rarely go really tall
                if ((rnd -= 9) <= 0)
                {
                    verHeightGain = 2 + caveRand.NextFloat() * caveRand.NextFloat() * 7;
                }
                else
                // Rarely large lava caverns
                if ((rnd -= 100) <= 0)
                {
                    if (posY < 19)
                    {
                        verHeightGain = 2 + caveRand.NextFloat() * caveRand.NextFloat() * 5;
                        horRadiusGain = 4 + caveRand.NextFloat() * caveRand.NextFloat() * 9;
                    }
                }

                sizeChangeSpeedAccum = Math.Max(0.1f, sizeChangeSpeedAccum + sizeChangeSpeedGain * 0.05f);
                sizeChangeSpeedGain -= 0.02f;

                horRadiusGainAccum = Math.Max(0, horRadiusGainAccum + horRadiusGain * sizeChangeSpeedAccum);
                horRadiusGain     -= 0.45f;

                horRadiusLossAccum = Math.Max(0, horRadiusLossAccum + horRadiusLoss * sizeChangeSpeedAccum);
                horRadiusLoss     -= 0.4f;

                verHeightGainAccum = Math.Max(0, verHeightGainAccum + verHeightGain * sizeChangeSpeedAccum);
                verHeightGain     -= 0.45f;

                verHeightLossAccum = Math.Max(0, verHeightLossAccum + verHeightLoss * sizeChangeSpeedAccum);
                verHeightLoss     -= 0.4f;

                horAngle  += curviness * horAngleChange;
                vertAngle += curviness * vertAngleChange;



                vertAngleChange = 0.9f * vertAngleChange + (caveRand.NextFloat() - caveRand.NextFloat()) * caveRand.NextFloat() * 3;
                horAngleChange  = 0.9f * horAngleChange + (caveRand.NextFloat() - caveRand.NextFloat()) * caveRand.NextFloat() * 1;


                if (caveRand.NextInt(140) == 0)
                {
                    horAngleChange *= caveRand.NextFloat() * 6;
                }

                // Horizontal branch
                int brand = branchRand + 2 * Math.Max(0, (int)posY - (TerraGenConfig.seaLevel - 20)); // Lower chance of branches above sealevel because Saraty does not like strongly cut out mountains
                if ((vertRadius > 1 || horRadius > 1) && branchLevel < 3 && caveRand.NextInt(brand) == 0)
                {
                    CarveTunnel(
                        chunks,
                        chunkX,
                        chunkZ,
                        posX, posY + verHeightGainAccum / 2, posZ,
                        horAngle + (caveRand.NextFloat() + caveRand.NextFloat() - 1) + GameMath.PI,
                        vertAngle + (caveRand.NextFloat() - 0.5f) * (caveRand.NextFloat() - 0.5f),
                        horizontalSize,
                        verticalSize + verHeightGainAccum,
                        currentIteration,
                        maxIterations - (int)(caveRand.NextFloat() * 0.5 * maxIterations),
                        branchLevel + 1
                        );
                }

                // Vertical branch
                if (horRadius > 3 && posY > 60 && branchLevel < 1 && caveRand.NextInt(60) == 0)
                {
                    CarveShaft(
                        chunks,
                        chunkX,
                        chunkZ,
                        posX, posY + verHeightGainAccum / 2, posZ,
                        horAngle + (caveRand.NextFloat() + caveRand.NextFloat() - 1) + GameMath.PI,
                        -GameMath.PI / 2 - 0.1f + 0.2f * caveRand.NextFloat(),
                        Math.Min(3.5f, horRadius - 1),
                        verticalSize + verHeightGainAccum,
                        currentIteration,
                        maxIterations - (int)(caveRand.NextFloat() * 0.5 * maxIterations) + (int)((posY / 5) * (0.5f + 0.5f * caveRand.NextFloat())),
                        branchLevel
                        );

                    branchLevel++;
                }



                if (horRadius >= 2 && caveRand.NextInt(5) == 0)
                {
                    continue;
                }

                // Check just to prevent unnecessary calculations
                // As long as we are outside the currently generating chunk, we don't need to generate anything
                if (posX <= -horRadius * 2 || posX >= chunksize + horRadius * 2 || posZ <= -horRadius * 2 || posZ >= chunksize + horRadius * 2)
                {
                    continue;
                }

                SetBlocks(chunks, horRadius, vertRadius + verHeightGainAccum, posX, posY + verHeightGainAccum / 2, posZ, terrainheightmap, rainheightmap, chunkX, chunkZ);
            }
        }
Example #26
0
        private void OnChunkColumnGeneration(IServerChunk[] chunks, int chunkX, int chunkZ, ITreeAttribute chunkGenParams = null)
        {
            int seaLevel = api.World.SeaLevel;
            int mapSizeY = api.WorldManager.MapSizeY;

            var veinMaps = chunks[0].MapChunk.MapRegion.GetModdata <Dictionary <string, IntDataMap2D> >("veinmaps");
            var oreMaps  = chunks[0].MapChunk.MapRegion.OreMaps;

            ushort[] heightMap = chunks[0].MapChunk.RainHeightMap;

            int chunksize = api.World.BlockAccessor.ChunkSize;

            int regionChunkSize = api.WorldManager.RegionSize / chunksize;

            int rdx = chunkX % regionChunkSize;
            int rdz = chunkZ % regionChunkSize;

            foreach (var vein in veinMaps)
            {
                if (!DepositByCode.ContainsKey(vein.Key))
                {
                    continue;
                }

                var deposit = DepositByCode[vein.Key];

                Dictionary <int, ResolvedDepositBlock> placeBlockByInBlockId   = deposit.GeneratorInst.GetField <Dictionary <int, ResolvedDepositBlock> >("placeBlockByInBlockId");
                Dictionary <int, ResolvedDepositBlock> surfaceBlockByInBlockId = deposit.GeneratorInst.GetField <Dictionary <int, ResolvedDepositBlock> >("surfaceBlockByInBlockId");

                var oreMap = oreMaps[vein.Key];

                var veinMap = vein.Value;

                float veinStep = (float)veinMap.InnerSize / regionChunkSize;
                float oreStep  = (float)oreMap.InnerSize / regionChunkSize;


                for (int x = 0; x < chunksize; x++)
                {
                    for (int z = 0; z < chunksize; z++)
                    {
                        rand.InitPositionSeed(chunkX + x, chunkZ + z);
                        int dCx = rand.NextInt(9) - 4;
                        int dCz = rand.NextInt(9) - 4;

                        int height = heightMap[z * chunksize + x];

                        veinAtPos.Value    = veinMap.GetInt((int)(rdx * veinStep + x), (int)(rdz * veinStep + z));
                        surfaceAtPos.Value = veinMap.GetInt((int)GameMath.Clamp(rdx * veinStep + (x + dCx), 0, veinMap.Size - 1), (int)GameMath.Clamp(rdz * veinStep + (z + dCz), 0, veinMap.Size - 1));

                        if (veinAtPos.Value == 0 && surfaceAtPos.Value == 0)
                        {
                            continue;
                        }

                        int  oreUpLeft   = oreMap.GetUnpaddedInt((int)(rdx * oreStep), (int)(rdz * oreStep));
                        int  oreUpRight  = oreMap.GetUnpaddedInt((int)(rdx * oreStep + oreStep), (int)(rdz * oreStep));
                        int  oreBotLeft  = oreMap.GetUnpaddedInt((int)(rdx * oreStep), (int)(rdz * oreStep + oreStep));
                        int  oreBotRight = oreMap.GetUnpaddedInt((int)(rdx * oreStep + oreStep), (int)(rdz * oreStep + oreStep));
                        uint oreMapInt   = (uint)GameMath.BiLerp(oreUpLeft, oreUpRight, oreBotLeft, oreBotRight, (float)x / chunksize, (float)z / chunksize);

                        float oreMapRel = ((oreMapInt & ~0xFF00FF) >> 8) / 15f;

                        if (veinAtPos.Rrel > 0.0)
                        {
                            int y = (int)((veinAtPos.Grel * mapSizeY) % height);

                            int depth = (int)(veinAtPos.Rrel * 10) + 1;

                            for (int dy = -depth; dy < depth; dy++)
                            {
                                if (y + dy > 0 && y + dy < mapSizeY)
                                {
                                    int chunkY = (y + dy) / chunksize;
                                    int lY     = (y + dy) % chunksize;

                                    int index3d = (chunksize * lY + z) * chunksize + x;
                                    int blockId = chunks[chunkY].Blocks[index3d];
                                    if (placeBlockByInBlockId?.ContainsKey(blockId) ?? false)
                                    {
                                        var blocks = placeBlockByInBlockId[blockId].Blocks;

                                        chunks[chunkY].Blocks[index3d] = blocks[(int)(oreMapRel * (blocks.Length - 1))].Id;

                                        if (deposit.ChildDeposits != null)
                                        {
                                            foreach (var child in deposit.ChildDeposits)
                                            {
                                                if (veinAtPos.Brel > 0.5)
                                                {
                                                    Dictionary <int, ResolvedDepositBlock> childPlaceBlockByInBlockId   = child.GeneratorInst.GetField <Dictionary <int, ResolvedDepositBlock> >("placeBlockByInBlockId");
                                                    Dictionary <int, ResolvedDepositBlock> childSurfaceBlockByInBlockId = child.GeneratorInst.GetField <Dictionary <int, ResolvedDepositBlock> >("surfaceBlockByInBlockId");

                                                    if (childPlaceBlockByInBlockId.ContainsKey(blockId))
                                                    {
                                                        blocks = childPlaceBlockByInBlockId[blockId].Blocks;
                                                        chunks[chunkY].Blocks[index3d] = blocks[(int)(oreMapRel * (blocks.Length - 1))].Id;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        if (surfaceAtPos.Rrel > 0.0)
                        {
                            //gen surface deposits
                            int y = (int)((surfaceAtPos.Grel * mapSizeY) % height);

                            int chunkY = y / chunksize;
                            int lY     = y % chunksize;

                            int index3d = (chunksize * lY + z) * chunksize + x;
                            int blockId = chunks[chunkY].Blocks[index3d];

                            if (surfaceBlockByInBlockId?.ContainsKey(blockId) ?? false)
                            {
                                if (height < mapSizeY && surfaceAtPos.Brel > 0.5f)
                                {
                                    Block belowBlock = api.World.Blocks[chunks[height / chunksize].Blocks[(height % chunksize * chunksize + z) * chunksize + x]];

                                    index3d = ((height + 1) % chunksize * chunksize + z) * chunksize + x;
                                    if (belowBlock.SideSolid[BlockFacing.UP.Index] && chunks[(height + 1) / chunksize].Blocks[index3d] == 0)
                                    {
                                        chunks[(height + 1) / chunksize].Blocks[index3d] = surfaceBlockByInBlockId[blockId].Blocks[0].BlockId;
#if DEBUG
                                        //so I can see it better when debugging
                                        index3d = (height % chunksize * chunksize + z) * chunksize + x;
                                        chunks[height / chunksize].Blocks[index3d] = 1;
#endif
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }