예제 #1
0
        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;
                }
            }
        }
예제 #2
0
        public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldgenRandom)
        {
            int fruit = (int)Math.Round(worldgenRandom.NextDouble() * 2.0);

            GenPalmTree(blockAccessor, pos, fruit);
            return(true);
        }
예제 #3
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);
            }
        }
예제 #4
0
        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);
        }
예제 #5
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));
                            }
                        }
                    }
                }
            }
        }
예제 #6
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);
        }
예제 #7
0
        public void GenPalmTree(IBlockAccessor blockAccessor, BlockPos pos, int fruit)
        {
            Block block = blockAccessor.GetBlock(pos.DownCopy());

            if (block.FirstCodePart() == "sand")
            {
                for (int i = 0; i < bottomOffsets.Length; i++)
                {
                    Block d = blockAccessor.GetBlock(pos.X + bottomOffsets[i].X, pos.Y + bottomOffsets[i].Y, pos.Z + bottomOffsets[i].Z);
                    if (d.LiquidCode == "water")
                    {
                        for (int k = 0; k < offsets.Length; k++)
                        {
                            Block c = blockAccessor.GetBlock(pos.X + offsets[i].X, pos.Y + offsets[i].Y, pos.Z + offsets[i].Z);
                            if (c.Class == Class)
                            {
                                return;
                            }
                        }
                        rand.InitPositionSeed(pos.X, pos.Y);
                        Block[] stretchedTrunk = trunk.Stretch((int)(rand.NextDouble() * (maxTreeSize)));

                        BlockPos top = new BlockPos(pos.X, pos.Y + stretchedTrunk.Length, pos.Z);
                        for (int j = 0; j < stretchedTrunk.Length; j++)
                        {
                            blockAccessor.SetBlock(stretchedTrunk[j].BlockId, new BlockPos(pos.X, pos.Y + j, pos.Z));
                        }
                        blockAccessor.SetBlock(tip.BlockId, top);
                        blockAccessor.SpawnBlockEntity("PalmTree", top);

                        GenFrondAndFruits(top, blockAccessor, stretchedTrunk.Length, fruit);
                        break;
                    }
                }
            }
            return;
        }
예제 #8
0
        public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldGenRand)
        {
            if (!HasSolidGround(blockAccessor, pos))
            {
                return(false);
            }

            int blockId = BlockId;

            if (worldGenRand.NextDouble() <= 0.20)
            {
                blockId = blockAccessor.GetBlock(CodeWithPath("looseflints-" + Variant["rock"] + "-free")).BlockId;
            }

            Block block = blockAccessor.GetBlock(pos);

            if (block.IsReplacableBy(this) && !block.IsLiquid())
            {
                blockAccessor.SetBlock(blockId, pos);
                return(true);
            }

            return(false);
        }
예제 #9
0
 public void TriggerTransition()
 {
     TriggerTransition(30 + (float)Rand.NextDouble() * 60 * 60 / ws.api.World.Calendar.SpeedOfTime);
 }
예제 #10
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);
        }
예제 #11
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);
                        }
                    }
                }
            }
        }
예제 #12
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);
                    }
                }
            }
        }
예제 #13
0
        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);
        }
예제 #14
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--;
                    }
                }
            }
        }
예제 #15
0
        public bool Suitable(float temp, float rain, float yRel, LCGRandom rnd)
        {
            float transDistance = MinTemp - temp + transSize;

            return(rain >= MinRain && rain <= MaxRain && MinY <= yRel && MaxY >= yRel && transDistance <= rnd.NextDouble() * transSize);
        }
        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);
                    }
                }
            }
        }