Пример #1
0
        public float GetLerpedCenterPixel(float x, float y, float z)
        {
            int posXLeft  = (int)Math.Floor(x - 0.5f);
            int posXRight = posXLeft + 1;

            int posYBot = (int)Math.Floor(y - 0.5f);
            int posYTop = posYBot + 1;

            int posZLeft  = (int)Math.Floor(z - 0.5f);
            int posZRight = posZLeft + 1;

            float fx = x - (posXLeft + 0.5f);
            float fy = y - (posYBot + 0.5f);
            float fz = z - (posZLeft + 0.5f);

            float up = GameMath.BiLerp(
                Data[(posYBot * Length + posZLeft) * Width + posXLeft],
                Data[(posYBot * Length + posZLeft) * Width + posXRight],
                Data[(posYBot * Length + posZRight) * Width + posXLeft],
                Data[(posYBot * Length + posZRight) * Width + posXRight],
                fx, fz
                );

            float down = GameMath.BiLerp(
                Data[(posYTop * Length + posZLeft) * Width + posXLeft],
                Data[(posYTop * Length + posZLeft) * Width + posXRight],
                Data[(posYTop * Length + posZRight) * Width + posXLeft],
                Data[(posYTop * Length + posZRight) * Width + posXRight],
                fx, fz
                );

            return(GameMath.Lerp(down, up, fy));
        }
Пример #2
0
        double[] GetTerrainNoise3D(double[] octX0, double[] octX1, double[] octX2, double[] octX3, double[] octThX0, double[] octThX1, double[] octThX2, double[] octThX3, int xPos, int yPos, int zPos)
        {
            for (int x = 0; x < paddedNoiseWidth; x++)
            {
                for (int z = 0; z < paddedNoiseWidth; z++)
                {
                    for (int i = 0; i < TerraGenConfig.terrainGenOctaves; i++)
                    {
                        lerpedAmps[i] = GameMath.BiLerp(octX0[i], octX1[i], octX2[i], octX3[i], (double)x / paddedNoiseWidth, (double)z / paddedNoiseWidth);
                        lerpedTh[i]   = GameMath.BiLerp(octThX0[i], octThX1[i], octThX2[i], octThX3[i], (double)x / paddedNoiseWidth, (double)z / paddedNoiseWidth);
                    }

                    for (int y = 0; y < paddedNoiseHeight; y++)
                    {
                        noiseTemp[NoiseIndex3d(x, y, z)] = TerrainNoise.Noise(
                            (xPos + x),
                            (yPos + y) / TerraGenConfig.terrainNoiseVerticalScale,
                            (zPos + z),
                            lerpedAmps,
                            lerpedTh
                            );
                    }
                }
            }

            return(noiseTemp);
        }
Пример #3
0
        double[] GetTerrainNoise3D(double[] octX0, double[] octX1, double[] octX2, double[] octX3, double[] octThX0, double[] octThX1, double[] octThX2, double[] octThX3, int xPos, int yPos, int zPos)
        {
            for (int x = 0; x < paddedNoiseWidth; x++)
            {
                for (int z = 0; z < paddedNoiseWidth; z++)
                {
                    for (int i = 0; i < TerraGenConfig.terrainGenOctaves; i++)
                    {
                        lerpedAmps[i] = GameMath.BiLerp(octX0[i], octX1[i], octX2[i], octX3[i], (double)x / paddedNoiseWidth, (double)z / paddedNoiseWidth);
                        lerpedTh[i]   = GameMath.BiLerp(octThX0[i], octThX1[i], octThX2[i], octThX3[i], (double)x / paddedNoiseWidth, (double)z / paddedNoiseWidth);
                    }

                    float distx = (float)distort2dx.Noise(xPos + x, zPos + z);
                    float distz = (float)distort2dz.Noise(xPos + x, zPos + z);

                    for (int y = 0; y < paddedNoiseHeight; y++)
                    {
                        noiseTemp[NoiseIndex3d(x, y, z)] = TerrainNoise.Noise(
                            (xPos + x) + (distx > 0 ? Math.Max(0, distx - 10) : Math.Min(0, distx + 10)),
                            (yPos + y) / TerraGenConfig.terrainNoiseVerticalScale,
                            (zPos + z) + (distz > 0 ? Math.Max(0, distz - 10) : Math.Min(0, distz + 10)),
                            lerpedAmps,
                            lerpedTh
                            );
                    }
                }
            }

            return(noiseTemp);
        }
Пример #4
0
        public float GetLerped(float x, float y, float z)
        {
            int posXLeft  = (int)x;
            int posXRight = posXLeft + 1;

            int posYBot = (int)y;
            int posYTop = posYBot + 1;

            int posZLeft  = (int)z;
            int posZRight = posZLeft + 1;

            float fx = x - (int)x;
            float fy = y - (int)y;
            float fz = z - (int)z;

            float down = GameMath.BiLerp(
                Data[(posYBot * Length + posZLeft) * Width + posXLeft],
                Data[(posYBot * Length + posZLeft) * Width + posXRight],
                Data[(posYBot * Length + posZRight) * Width + posXLeft],
                Data[(posYBot * Length + posZRight) * Width + posXRight],
                fx, fz
                );

            float up = GameMath.BiLerp(
                Data[(posYTop * Length + posZLeft) * Width + posXLeft],
                Data[(posYTop * Length + posZLeft) * Width + posXRight],
                Data[(posYTop * Length + posZRight) * Width + posXLeft],
                Data[(posYTop * Length + posZRight) * Width + posXRight],
                fx, fz
                );

            return(GameMath.Lerp(down, up, fy));
        }
Пример #5
0
        public PrecipitationState GetPrecipitationState(Vec3d pos)
        {
            LoadAdjacentSimsAndLerpValues(pos);

            double level = GameMath.BiLerp(
                adjacentSims[0].weatherData.PrecIntensity,
                adjacentSims[1].weatherData.PrecIntensity,
                adjacentSims[2].weatherData.PrecIntensity,
                adjacentSims[3].weatherData.PrecIntensity,
                lerpLeftRight,
                lerpTopBot
                );

            double size = GameMath.BiLerp(
                adjacentSims[0].weatherData.PrecParticleSize,
                adjacentSims[1].weatherData.PrecParticleSize,
                adjacentSims[2].weatherData.PrecParticleSize,
                adjacentSims[3].weatherData.PrecParticleSize,
                lerpLeftRight,
                lerpTopBot
                );

            EnumPrecipitationType top = lerpLeftRight < 0.5 ? adjacentSims[0].weatherData.nowPrecType : adjacentSims[1].weatherData.nowPrecType;
            EnumPrecipitationType bot = lerpLeftRight < 0.5 ? adjacentSims[2].weatherData.nowPrecType : adjacentSims[3].weatherData.nowPrecType;

            EnumPrecipitationType type = lerpTopBot < 0.5 ? top : bot;

            return(new PrecipitationState()
            {
                Level = level,
                ParticleSize = size,
                Type = type
            });
        }
Пример #6
0
        void genShrubs(int chunkX, int chunkZ)
        {
            int triesShrubs = (int)treeSupplier.treeGenProps.shrubsPerChunk.nextFloat();

            int   dx, dz, x, z;
            Block block;

            while (triesShrubs > 0)
            {
                triesShrubs--;

                dx = rnd.Next(chunksize);
                dz = rnd.Next(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);
                if (block.Fertility == 0)
                {
                    continue;
                }

                // Place according to forest value
                float treeDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)dx / chunksize, (float)dz / chunksize);
                int   climate     = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
                float shrubChance = GameMath.BiLerp(shrubUpLeft, shrubUpRight, shrubBotLeft, shrubBotRight, (float)dx / chunksize, (float)dz / chunksize);


                if (rnd.NextDouble() > (shrubChance / 255f) * (shrubChance / 255f))
                {
                    continue;
                }
                TreeGenForClimate treegenParams = treeSupplier.GetRandomShrubGenForClimate(climate, (int)shrubChance, y);

                if (treegenParams != null)
                {
                    if (blockAccessor.GetBlock(tmpPos.X, tmpPos.Y, tmpPos.Z).Replaceable >= 6000)
                    {
                        tmpPos.Y--;
                    }

                    treegenParams.treeGen.GrowTree(
                        blockAccessor,
                        tmpPos,
                        treegenParams.size,
                        treegenParams.vinesGrowthChance
                        );
                }
            }
        }
 public double GetBlendedUndulatingCloudModeness()
 {
     return(GameMath.BiLerp(
                adjacentSims[0].GetBlendedUndulatingCloudModeness(),
                adjacentSims[1].GetBlendedUndulatingCloudModeness(),
                adjacentSims[2].GetBlendedUndulatingCloudModeness(),
                adjacentSims[3].GetBlendedUndulatingCloudModeness(),
                lerpLeftRight, lerpTopBot
                ));
 }
 protected double pgetBlendedUndulatingCloudModeness()
 {
     return(GameMath.BiLerp(
                AdjacentSims[0].GetBlendedUndulatingCloudModeness(),
                AdjacentSims[1].GetBlendedUndulatingCloudModeness(),
                AdjacentSims[2].GetBlendedUndulatingCloudModeness(),
                AdjacentSims[3].GetBlendedUndulatingCloudModeness(),
                LerpLeftRight, LerpTopBot
                ));
 }
 public double GetBlendedCloudBrightness(float b)
 {
     return(GameMath.BiLerp(
                adjacentSims[0].GetBlendedCloudBrightness(b),
                adjacentSims[1].GetBlendedCloudBrightness(b),
                adjacentSims[2].GetBlendedCloudBrightness(b),
                adjacentSims[3].GetBlendedCloudBrightness(b),
                lerpLeftRight, lerpTopBot
                ));
 }
 public double GetBlendedCloudThicknessAt(int cloudTileX, int cloudTileZ)
 {
     return(GameMath.BiLerp(
                adjacentSims[0].GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ),
                adjacentSims[1].GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ),
                adjacentSims[2].GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ),
                adjacentSims[3].GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ),
                lerpLeftRight, lerpTopBot
                ));
 }
 protected double pgetWindSpeed(double posY)
 {
     return(GameMath.BiLerp(
                AdjacentSims[0].GetWindSpeed(posY),
                AdjacentSims[1].GetWindSpeed(posY),
                AdjacentSims[2].GetWindSpeed(posY),
                AdjacentSims[3].GetWindSpeed(posY),
                LerpLeftRight,
                LerpTopBot
                ));
 }
Пример #12
0
        private void OnChunkColumnGen(IServerChunk[] chunks, int chunkX, int chunkZ, ITreeAttribute chunkGenParams)
        {
            IntMap   beachMap = chunks[0].MapChunk.MapRegion.BeachMap;
            Vec3i    climate  = chunks[0].MapChunk.MapRegion.ClimateMap.ToClimateVec(chunkX, chunkZ, api.WorldManager.RegionSize, chunksize);
            BlockPos pos      = new BlockPos();

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

            int regionChunkSize = api.WorldManager.RegionSize / chunksize;
            int rdx             = chunkX % regionChunkSize;
            int rdz             = chunkZ % regionChunkSize;

            float beachStep = (float)beachMap.InnerSize / regionChunkSize;

            int beachUpLeft   = beachMap.GetUnpaddedInt((int)(rdx * beachStep), (int)(rdz * beachStep));
            int beachUpRight  = beachMap.GetUnpaddedInt((int)(rdx * beachStep + beachStep), (int)(rdz * beachStep));
            int beachBotLeft  = beachMap.GetUnpaddedInt((int)(rdx * beachStep), (int)(rdz * beachStep + beachStep));
            int beachBotRight = beachMap.GetUnpaddedInt((int)(rdx * beachStep + beachStep), (int)(rdz * beachStep + beachStep));

            for (int x = 0; x < chunksize; x++)
            {
                for (int z = 0; z < chunksize; z++)
                {
                    int y = heightMap[z * chunksize + x];

                    float beachRel = GameMath.BiLerp(beachUpLeft, beachUpRight, beachBotLeft, beachBotRight, (float)x / chunksize, (float)z / chunksize) / 255f;
                    float tempRel  = climate.Z / 255f;
                    if (beachRel > 0.5 && tempRel > 0.5)
                    {
                        pos.X = chunkX * chunksize + x;
                        pos.Y = y + 1;
                        pos.Z = chunkZ * chunksize + z;

                        var a      = api.ModLoader.GetModSystem <GenBlockLayers>();
                        int rockID = chunks[0].MapChunk.TopRockIdMap[z * chunksize + x];

                        if (a.blockLayerConfig.BeachLayer.BlockIdMapping.TryGetValue(rockID, out int sand))
                        {
                            int lY     = y % chunksize;
                            int i3d    = (chunksize * lY + z) * chunksize + x;
                            int chunkY = y / chunksize;

                            double noise = sNoise.Noise(rdx + x, rdx + z);

                            if (chunks[chunkY].Blocks[i3d] == sand && noise > 0.84)
                            {
                                GenPalmTree(blockAccessor, pos, sizeNoise.Noise(pos.X, pos.Y, pos.Z), fruitNoise.Noise(pos.X, pos.Y, pos.Z), frondNoise.Noise(pos.X, pos.Y, pos.Z));
                            }
                        }
                    }
                }
            }
        }
Пример #13
0
        public double GetRainFall(Vec3d pos)
        {
            LoadAdjacentSimsAndLerpValues(pos);

            return(GameMath.BiLerp(
                       adjacentSims[0].weatherData.PrecIntensity,
                       adjacentSims[1].weatherData.PrecIntensity,
                       adjacentSims[2].weatherData.PrecIntensity,
                       adjacentSims[3].weatherData.PrecIntensity,
                       lerpLeftRight,
                       lerpTopBot
                       ));
        }
Пример #14
0
        public float GetUnpaddedIntLerped(float x, float z)
        {
            int ix = (int)x;
            int iz = (int)z;

            return(GameMath.BiLerp(
                       Data[(iz + TopLeftPadding) * Size + ix + TopLeftPadding],
                       Data[(iz + TopLeftPadding) * Size + ix + 1 + TopLeftPadding],
                       Data[(iz + 1 + TopLeftPadding) * Size + ix + TopLeftPadding],
                       Data[(iz + 1 + TopLeftPadding) * Size + ix + 1 + TopLeftPadding],
                       x - ix, z - iz
                       ));
        }
Пример #15
0
        public double GetWindSpeed(Vec3d pos)
        {
            LoadAdjacentSimsAndLerpValues(pos);

            return(GameMath.BiLerp(
                       adjacentSims[0].GetWindSpeed(pos.Y),
                       adjacentSims[1].GetWindSpeed(pos.Y),
                       adjacentSims[2].GetWindSpeed(pos.Y),
                       adjacentSims[3].GetWindSpeed(pos.Y),
                       lerpLeftRight,
                       lerpTopBot
                       ));
        }
        protected double pgetBlendedCloudBrightness(float b)
        {
            double bright = GameMath.BiLerp(
                AdjacentSims[0].GetBlendedCloudBrightness(b),
                AdjacentSims[1].GetBlendedCloudBrightness(b),
                AdjacentSims[2].GetBlendedCloudBrightness(b),
                AdjacentSims[3].GetBlendedCloudBrightness(b),
                LerpLeftRight, LerpTopBot
                );

            double rainbright = rainOverlayData.State.nowCloudBrightness;

            return(GameMath.Lerp(bright, rainbright, lerpRainCloudOverlay));
        }
        protected double pgetBlendedCloudThicknessAt(int cloudTileX, int cloudTileZ)
        {
            double thick = GameMath.BiLerp(
                AdjacentSims[0].GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ),
                AdjacentSims[1].GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ),
                AdjacentSims[2].GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ),
                AdjacentSims[3].GetBlendedCloudThicknessAt(cloudTileX, cloudTileZ),
                LerpLeftRight, LerpTopBot
                );

            double rainThick = rainOverlayData.State.nowbaseThickness;

            return(GameMath.Lerp(thick, rainThick, lerpRainCloudOverlay));
        }
        protected double pgetBlendedCloudOpaqueness()
        {
            double opaque = GameMath.BiLerp(
                AdjacentSims[0].GetBlendedCloudOpaqueness(),
                AdjacentSims[1].GetBlendedCloudOpaqueness(),
                AdjacentSims[2].GetBlendedCloudOpaqueness(),
                AdjacentSims[3].GetBlendedCloudOpaqueness(),
                LerpLeftRight, LerpTopBot
                );

            double rainopaque = rainOverlayData.State.nowbaseOpaqueness;

            return(GameMath.Lerp(opaque, rainopaque, lerpRainCloudOverlay));
        }
Пример #19
0
        public bool TryGetCachedWeather(double x, double z, ref float[] weather)
        {
            int cX = (int)Math.Round(x / chunksize);
            int cZ = (int)Math.Round(z / chunksize);

            int   startX = (cX - 1) * chunksize + chunksize / 2;
            int   startZ = (cZ - 1) * chunksize + chunksize / 2;
            float dx     = (float)((x - startX) / chunksize);
            float dz     = (float)((z - startZ) / chunksize);

            double hoursTotal = world.Calendar.TotalHours;
            double timespan   = snap2.hoursTotal - snap1.hoursTotal;

            long topleft     = ((cX - 1) << 32) | (cZ - 1);
            long topright    = (cX << 32) | (cZ - 1);
            long bottomright = (cX << 32) | cZ;
            long bottomleft  = ((cX - 1) << 32) | cZ;

            bool success = true;

            float[] wtl1 = null, wtr1 = null, wbr1 = null, wbl1 = null, wtl2 = null, wtr2 = null, wbr2 = null, wbl2 = null;

            success = success && snap1.WeatherNoiseByChunk.TryGetValue(topleft, out wtl1);
            success = success && snap1.WeatherNoiseByChunk.TryGetValue(topright, out wtr1);
            success = success && snap1.WeatherNoiseByChunk.TryGetValue(bottomright, out wbr1);
            success = success && snap1.WeatherNoiseByChunk.TryGetValue(bottomleft, out wbl1);

            success = success && snap2.WeatherNoiseByChunk.TryGetValue(topleft, out wtl2);
            success = success && snap2.WeatherNoiseByChunk.TryGetValue(topright, out wtr2);
            success = success && snap2.WeatherNoiseByChunk.TryGetValue(bottomright, out wbr2);
            success = success && snap2.WeatherNoiseByChunk.TryGetValue(bottomleft, out wbl2);

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

            for (int i = 0; i < weather.Length; i++)
            {
                float weatherSnap1 = GameMath.BiLerp(wtl1[i], wtr1[i], wbr1[i], wbl1[i], dx, dz);
                float weatherSnap2 = GameMath.BiLerp(wtl2[i], wtr2[i], wbr2[i], wbl2[i], dx, dz);

                weather[i] = GameMath.Lerp(weatherSnap1, weatherSnap2, (float)((hoursTotal - snap1.hoursTotal) / timespan));
            }

            return(true);
        }
Пример #20
0
        public float GetIntLerpedCorrectly(float x, float z)
        {
            int posXLeft  = (int)Math.Floor(x - 0.5f);
            int posXRight = posXLeft + 1;

            int posZLeft  = (int)Math.Floor(z - 0.5f);
            int posZRight = posZLeft + 1;

            float fx = x - (posXLeft + 0.5f);
            float fz = z - (posZLeft + 0.5f);

            return(GameMath.BiLerp(
                       Data[(posZLeft + TopLeftPadding) * Size + posXLeft + TopLeftPadding],
                       Data[(posZLeft + TopLeftPadding) * Size + posXRight + TopLeftPadding],
                       Data[(posZRight + TopLeftPadding) * Size + posXLeft + TopLeftPadding],
                       Data[(posZRight + TopLeftPadding) * Size + posXRight + TopLeftPadding],
                       fx, fz
                       ));
        }
        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.Next(chunksize);
                    dz = rnd.Next(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;
                    int   climate   = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
                    //float shrubChance = GameMath.BiLerp(shrubUpLeft, shrubUpRight, shrubBotLeft, shrubBotRight, (float)dx / chunksize, (float)dz / chunksize);

                    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);
                        }
                    }
                }
            }
        }
Пример #22
0
        private void OnChunkColumnGeneration(IServerChunk[] chunks, int chunkX, int chunkZ, ITreeAttribute chunkGenParams = null)
        {
            rnd.InitPositionSeed(chunkX, chunkZ);

            IntDataMap2D forestMap  = chunks[0].MapChunk.MapRegion.ForestMap;
            IntDataMap2D climateMap = chunks[0].MapChunk.MapRegion.ClimateMap;
            IntDataMap2D beachMap   = chunks[0].MapChunk.MapRegion.BeachMap;

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

            int regionChunkSize = api.WorldManager.RegionSize / chunksize;
            int rdx             = chunkX % regionChunkSize;
            int rdz             = chunkZ % regionChunkSize;

            // Amount of data points per chunk
            float climateStep = (float)climateMap.InnerSize / regionChunkSize;
            float forestStep  = (float)forestMap.InnerSize / regionChunkSize;
            float beachStep   = (float)beachMap.InnerSize / regionChunkSize;

            // Retrieves the map data on the chunk edges
            int forestUpLeft   = forestMap.GetUnpaddedInt((int)(rdx * forestStep), (int)(rdz * forestStep));
            int forestUpRight  = forestMap.GetUnpaddedInt((int)(rdx * forestStep + forestStep), (int)(rdz * forestStep));
            int forestBotLeft  = forestMap.GetUnpaddedInt((int)(rdx * forestStep), (int)(rdz * forestStep + forestStep));
            int forestBotRight = forestMap.GetUnpaddedInt((int)(rdx * forestStep + forestStep), (int)(rdz * forestStep + forestStep));

            int beachUpLeft   = beachMap.GetUnpaddedInt((int)(rdx * beachStep), (int)(rdz * beachStep));
            int beachUpRight  = beachMap.GetUnpaddedInt((int)(rdx * beachStep + beachStep), (int)(rdz * beachStep));
            int beachBotLeft  = beachMap.GetUnpaddedInt((int)(rdx * beachStep), (int)(rdz * beachStep + beachStep));
            int beachBotRight = beachMap.GetUnpaddedInt((int)(rdx * beachStep + beachStep), (int)(rdz * beachStep + beachStep));


            // increasing x -> left to right
            // increasing z -> top to bottom

            float transitionSize = blockLayerConfig.blockLayerTransitionSize;


            for (int x = 0; x < chunksize; x++)
            {
                for (int z = 0; z < chunksize; z++)
                {
                    // Some weird randomnes stuff to hide fundamental bugs in the climate transition system :D T_T   (maybe not bugs but just fundamental shortcomings of using lerp on a very low resolution map)
                    float distx = (float)distort2dx.Noise(chunkX * chunksize + x, chunkZ * chunksize + z);
                    float distz = (float)distort2dz.Noise(chunkX * chunksize + x, chunkZ * chunksize + z);

                    double posRand        = (double)GameMath.MurmurHash3(x + chunkX * chunksize, 1, z + chunkZ * chunksize) / int.MaxValue;
                    double transitionRand = (posRand + 1) * transitionSize;

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

                    int climate = climateMap.GetUnpaddedColorLerped(
                        rdx * climateStep + climateStep * (float)(x + distx) / chunksize,
                        rdz * climateStep + climateStep * (float)(z + distz) / chunksize
                        );

                    int   tempUnscaled = (climate >> 16) & 0xff;
                    int   rnd          = (int)(distx / 5);
                    float temp         = TerraGenConfig.GetScaledAdjustedTemperatureFloat(tempUnscaled, posY - TerraGenConfig.seaLevel + rnd);
                    float tempRel      = TerraGenConfig.GetAdjustedTemperature(tempUnscaled, posY - TerraGenConfig.seaLevel + rnd) / 255f;
                    float rainRel      = TerraGenConfig.GetRainFall((climate >> 8) & 0xff, posY + rnd) / 255f;
                    float forestRel    = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)x / chunksize, (float)z / chunksize) / 255f;
                    float beachRel     = GameMath.BiLerp(beachUpLeft, beachUpRight, beachBotLeft, beachBotRight, (float)x / chunksize, (float)z / chunksize) / 255f;

                    int prevY = posY;

                    posY = PutLayers(transitionRand, x, posY, z, chunks, rainRel, temp, tempUnscaled, heightMap);
                    int blockID = chunks[0].MapChunk.TopRockIdMap[z * chunksize + x];

                    GenBeach(x, prevY, z, chunks, rainRel, temp, beachRel, blockID);
                    PlaceTallGrass(x, prevY, z, chunks, rainRel, tempRel, temp, forestRel);


                    // Try again to put layers if above sealevel and we found over 10 air blocks
                    int foundAir = 0;
                    while (posY >= TerraGenConfig.seaLevel - 1)
                    {
                        int chunkY  = posY / chunksize;
                        int lY      = posY % chunksize;
                        int index3d = (chunksize * lY + z) * chunksize + x;
                        int blockId = chunks[chunkY].Blocks[index3d];

                        if (blockId == 0)
                        {
                            foundAir++;
                        }
                        else
                        {
                            if (foundAir >= 8)
                            {
                                //temp = TerraGenConfig.GetScaledAdjustedTemperatureFloat(tempUnscaled, posY - TerraGenConfig.seaLevel);
                                //rainRel = TerraGenConfig.GetRainFall((climate >> 8) & 0xff, posY) / 255f;
                                //PutLayers(transitionRand, x, posY, z, chunks, rainRel, temp, tempUnscaled, null);
                                break;
                            }
                            else
                            {
                                foundAir = 0;
                            }
                        }

                        posY--;
                    }
                }
            }
        }
Пример #23
0
        void genShrubs(int chunkX, int chunkZ)
        {
            int triesShrubs = (int)treeSupplier.treeGenProps.shrubsPerChunk.nextFloat();

            int   dx, dz, x, z;
            Block block;

            while (triesShrubs > 0)
            {
                triesShrubs--;

                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);
                if (block.Fertility == 0)
                {
                    continue;
                }

                // Place according to forest value
                int   climate     = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
                float shrubChance = GameMath.BiLerp(shrubUpLeft, shrubUpRight, shrubBotLeft, shrubBotRight, (float)dx / chunksize, (float)dz / chunksize);
                shrubChance = GameMath.Clamp(shrubChance + 255 * forestMod, 0, 255);

                if (rnd.NextDouble() > (shrubChance / 255f) * (shrubChance / 255f))
                {
                    continue;
                }
                TreeGenForClimate treegenParams = treeSupplier.GetRandomShrubGenForClimate(climate, (int)shrubChance, y);

                if (treegenParams != null)
                {
                    bool canGen = true;
                    for (int i = 0; i < structuresIntersectingChunk.Count; i++)
                    {
                        if (structuresIntersectingChunk[i].Location.Contains(tmpPos))
                        {
                            canGen = false; break;
                        }
                    }
                    if (!canGen)
                    {
                        continue;
                    }

                    if (blockAccessor.GetBlock(tmpPos.X, tmpPos.Y, tmpPos.Z).Replaceable >= 6000)
                    {
                        tmpPos.Y--;
                    }

                    treegenParams.treeGen.GrowTree(
                        blockAccessor,
                        tmpPos,
                        treegenParams.size,
                        treegenParams.vinesGrowthChance
                        );
                }
            }
        }
Пример #24
0
        void genTrees(int chunkX, int chunkZ)
        {
            int   climate = GameMath.BiLerpRgbColor((float)0.5f, (float)0.5f, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
            float wetrel  = TerraGenConfig.GetRainFall((climate >> 8) & 0xff, heightmap[(chunksize / 2) * chunksize + chunksize / 2]) / 255f;
            float dryrel  = 1 - wetrel;

            float drypenalty = 1 - GameMath.Clamp(2f * (dryrel - 0.5f), 0, 0.8f); // Reduce tree generation by up to 70% in low rain places
            float wetboost   = 1 + 3 * Math.Max(0, wetrel - 0.75f);

            int   triesTrees = (int)(treeSupplier.treeGenProps.treesPerChunk.nextFloat() * drypenalty * wetboost);
            int   dx, dz, x, z;
            Block block;

            while (triesTrees > 0)
            {
                triesTrees--;

                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);
                if (block.Fertility == 0)
                {
                    continue;
                }

                // Place according to forest value
                float treeDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)dx / chunksize, (float)dz / chunksize);
                climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
                //float shrubChance = GameMath.BiLerp(shrubUpLeft, shrubUpRight, shrubBotLeft, shrubBotRight, (float)dx / chunksize, (float)dz / chunksize);

                treeDensity = GameMath.Clamp(treeDensity + forestMod * 255, 0, 255);

                float treeDensityNormalized = treeDensity / 255f;



                // 1 in 400 chance to always spawn a tree
                // otherwise go by tree density using a quadratic drop off to create clearer forest edges
                if (rnd.NextDouble() > Math.Max(0.0025, treeDensityNormalized * treeDensityNormalized) || forestMod <= -1)
                {
                    continue;
                }
                TreeGenForClimate treegenParams = treeSupplier.GetRandomTreeGenForClimate(climate, (int)treeDensity, y);

                if (treegenParams != null)
                {
                    bool canGen = true;
                    for (int i = 0; i < structuresIntersectingChunk.Count; i++)
                    {
                        if (structuresIntersectingChunk[i].Location.Contains(tmpPos))
                        {
                            canGen = false; break;
                        }
                    }
                    if (!canGen)
                    {
                        continue;
                    }

                    if (blockAccessor.GetBlock(tmpPos.X, tmpPos.Y, tmpPos.Z).Replaceable >= 6000)
                    {
                        tmpPos.Y--;
                    }

                    treegenParams.treeGen.GrowTree(
                        blockAccessor,
                        tmpPos,
                        treegenParams.size,
                        treegenParams.vinesGrowthChance
                        );
                }
            }
        }
        private string getWeatherInfo <T>(IPlayer player) where T : WeatherSystemBase
        {
            T wsys = api.ModLoader.GetModSystem <T>();

            Vec3d    plrPos = player.Entity.SidedPos.XYZ;
            BlockPos pos    = plrPos.AsBlockPos;

            var wreader = wsys.getWeatherDataReaderPreLoad();

            wreader.LoadAdjacentSimsAndLerpValues(plrPos, 1);

            int regionX = (int)pos.X / api.World.BlockAccessor.RegionSize;
            int regionZ = (int)pos.Z / api.World.BlockAccessor.RegionSize;

            WeatherSimulationRegion weatherSim;
            long index2d = wsys.MapRegionIndex2D(regionX, regionZ);

            wsys.weatherSimByMapRegion.TryGetValue(index2d, out weatherSim);
            if (weatherSim == null)
            {
                return("weatherSim is null. No idea what to do here");
            }

            StringBuilder sb = new StringBuilder();

            sb.AppendLine(string.Format("Weather by region:")); // (lerp-lr: {0}, lerp-bt: {1}), wsys.lerpLeftRight.ToString("0.##"), wsys.lerpTopBot.ToString("0.##")));
            string[] cornerNames = new string[] { "tl", "tr", "bl", "br" };

            //topBlendedWeatherData.SetLerped(adjacentSims[0].weatherData, adjacentSims[1].weatherData, (float)lerpLeftRight);
            //botBlendedWeatherData.SetLerped(adjacentSims[2].weatherData, adjacentSims[3].weatherData, (float)lerpLeftRight);
            //blendedWeatherData.SetLerped(topBlendedWeatherData, botBlendedWeatherData, (float)lerpTopBot);

            double tlLerp = GameMath.BiLerp(1, 0, 0, 0, wreader.LerpLeftRight, wreader.LerpTopBot);
            double trLerp = GameMath.BiLerp(0, 1, 0, 0, wreader.LerpLeftRight, wreader.LerpTopBot);
            double blLerp = GameMath.BiLerp(0, 0, 1, 0, wreader.LerpLeftRight, wreader.LerpTopBot);
            double brLerp = GameMath.BiLerp(0, 0, 0, 1, wreader.LerpLeftRight, wreader.LerpTopBot);

            int[] lerps = new int[] { (int)(100 * tlLerp), (int)(100 * trLerp), (int)(100 * blLerp), (int)(100 * brLerp) };

            for (int i = 0; i < 4; i++)
            {
                WeatherSimulationRegion sim = wreader.AdjacentSims[i];

                if (sim == wsys.dummySim)
                {
                    sb.AppendLine(string.Format("{0}: missing", cornerNames[i]));
                }
                else
                {
                    /*sb.AppendLine(string.Format("{10}% of {0}@{8}/{9}: {1}% {2}, {3}% {4}. Prec: {5}, Wind: {6} (v={7})",
                     *  cornerNames[i], (int)(100 * sim.Weight), sim.NewWePattern.GetWeatherName(), (int)(100 - 100 * sim.Weight),
                     *  sim.OldWePattern.GetWeatherName(), sim.weatherData.PrecIntensity.ToString("0.###"),
                     *  sim.CurWindPattern.GetWindName(), sim.GetWindSpeed(pos.Y).ToString("0.###"),
                     *  sim.regionX, sim.regionZ,
                     *  lerps[i]
                     * )) ;*/

                    sb.AppendLine(string.Format("{9}% of {0}@{7}/{8}: {1}% {2}, {3}% {4}. Wind: {5}, Event: {10} (v={6})",
                                                cornerNames[i], (int)(100 * sim.Weight), sim.NewWePattern.GetWeatherName(), (int)(100 - 100 * sim.Weight),
                                                sim.OldWePattern.GetWeatherName(),
                                                sim.CurWindPattern.GetWindName(), sim.GetWindSpeed(pos.Y).ToString("0.###"),
                                                sim.regionX, sim.regionZ,
                                                lerps[i],
                                                sim.CurWeatherEvent.config.Code
                                                ));
                }
            }

            //wsys.updateAdjacentAndBlendWeatherData();
            //WeatherDataSnapshot wData = wsys.blendedWeatherData;
            //sb.AppendLine(string.Format(string.Format("Blended:\nPrecipitation: {0}, Particle size: {1}, Type: {2}, Wind speed: {3}", wData.PrecIntensity, wData.PrecParticleSize, wData.BlendedPrecType, wsys.GetWindSpeed(plrPos))));
            ClimateCondition climate = api.World.BlockAccessor.GetClimateAt(player.Entity.Pos.AsBlockPos, EnumGetClimateMode.NowValues);

            sb.AppendLine(string.Format("Current precipitation: {0}%", (int)(climate.Rainfall * 100f)));
            sb.AppendLine(string.Format("Current wind: {0}", API.Config.GlobalConstants.CurrentWindSpeedClient));

            return(sb.ToString());
        }
Пример #26
0
        private void TrySpawnGroupAt(BlockPos origin, Vec3d posAsVec, EntityProperties entityType, EntityProperties[] grouptypes)
        {
            BlockPos pos = origin.Copy();

            float xRel = (float)(posAsVec.X % chunksize) / chunksize;
            float zRel = (float)(posAsVec.Z % chunksize) / chunksize;

            int   climate       = GameMath.BiLerpRgbColor(xRel, zRel, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
            float temp          = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, (int)posAsVec.Y - TerraGenConfig.seaLevel);
            float rain          = ((climate >> 8) & 0xff) / 255f;
            float forestDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, xRel, zRel);
            float shrubDensity  = GameMath.BiLerp(shrubsUpLeft, shrubsUpRight, shrubsBotLeft, shrubsBotRight, xRel, zRel);

            int spawned = 0;

            WorldGenSpawnConditions sc = entityType.Server.SpawnConditions.Worldgen;
            bool hasCompanions         = sc.Companions != null && sc.Companions.Length > 0;

            spawnPositions.Clear();

            int nextGroupSize = 0;
            int tries         = 10;

            while (nextGroupSize <= 0 && tries-- > 0)
            {
                float val = sc.GroupSize.nextFloat();
                nextGroupSize = (int)val + ((val - (int)val) > rnd.NextDouble() ? 1 : 0);
            }


            for (int i = 0; i < nextGroupSize * 4 + 5; i++)
            {
                if (spawned >= nextGroupSize)
                {
                    break;
                }

                EntityProperties typeToSpawn = entityType;

                // First entity 80% chance to spawn the dominant creature, every subsequent only 20% chance for males (or even lower if more than 5 companion types)
                double dominantChance = i == 0 ? 0.8 : Math.Min(0.2, 1f / grouptypes.Length);

                if (grouptypes.Length > 1 && rnd.NextDouble() > dominantChance)
                {
                    typeToSpawn = grouptypes[1 + rnd.Next(grouptypes.Length - 1)];
                }

                posAsVec.Set(pos.X + 0.5, pos.Y + 0.005, pos.Z + 0.5);

                IBlockAccessor blockAccesssor = wgenBlockAccessor.GetChunkAtBlockPos(pos.X, pos.Y, pos.Z) == null ? api.World.BlockAccessor : wgenBlockAccessor;

                IMapChunk mapchunk = blockAccesssor.GetMapChunkAtBlockPos(pos);
                if (mapchunk != null)
                {
                    ushort[] heightMap = mapchunk.WorldGenTerrainHeightMap;

                    pos.Y =
                        sc.TryOnlySurface ?
                        heightMap[((int)pos.Z % chunksize) * chunksize + ((int)pos.X % chunksize)] + 1 :
                        pos.Y
                    ;

                    xRel = (float)(posAsVec.X % chunksize) / chunksize;
                    zRel = (float)(posAsVec.Z % chunksize) / chunksize;

                    climate       = GameMath.BiLerpRgbColor(xRel, zRel, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
                    temp          = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, (int)posAsVec.Y - TerraGenConfig.seaLevel);
                    rain          = ((climate >> 8) & 0xff) / 255f;
                    forestDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, xRel, zRel) / 255f;
                    shrubDensity  = GameMath.BiLerp(shrubsUpLeft, shrubsUpRight, shrubsBotLeft, shrubsBotRight, xRel, zRel) / 255f;


                    if (CanSpawnAt(blockAccesssor, typeToSpawn, pos, posAsVec, sc, rain, temp, forestDensity, shrubDensity))
                    {
                        spawnPositions.Add(new SpawnOppurtunity()
                        {
                            ForType = typeToSpawn, Pos = posAsVec.Clone()
                        });
                        spawned++;
                    }
                }

                pos.X = origin.X + ((rnd.Next(11) - 5) + (rnd.Next(11) - 5)) / 2;
                pos.Z = origin.Z + ((rnd.Next(11) - 5) + (rnd.Next(11) - 5)) / 2;
            }


            // Only spawn if the group reached the minimum group size
            if (spawnPositions.Count >= nextGroupSize)
            {
                long herdId = api.WorldManager.GetNextHerdId();

                foreach (SpawnOppurtunity so in spawnPositions)
                {
                    Entity ent = CreateEntity(so.ForType, so.Pos);
                    if (ent is EntityAgent)
                    {
                        (ent as EntityAgent).HerdId = herdId;
                    }

                    if (wgenBlockAccessor.GetChunkAtBlockPos(pos.X, pos.Y, pos.Z) == null)
                    {
                        api.World.SpawnEntity(ent);
                    }
                    else
                    {
                        wgenBlockAccessor.AddEntity(ent);
                    }
                }

                //Console.WriteLine("Spawn a group of {0}x{1} at {2}", spawnPositions.Count, entityType.Code, origin);
            }
        }
Пример #27
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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Пример #28
0
        /// <summary>
        /// forceInitialPosY is for subdeposits
        /// </summary>
        /// <param name="chunks"></param>
        /// <param name="chunkX"></param>
        /// <param name="chunkZ"></param>
        /// <param name="offsetX"></param>
        /// <param name="offsetZ"></param>
        /// <param name="variant"></param>
        /// <param name="forceInitialPosY"></param>
        /// <returns></returns>
        Dictionary <Vec3i, DepositVariant> GenDeposit(IServerChunk[] chunks, int chunkX, int chunkZ, int offsetX, int offsetZ, DepositVariant variant, int?forceInitialPosY = null)
        {
            Dictionary <Vec3i, DepositVariant> SubDepositsToPlace = new Dictionary <Vec3i, DepositVariant>();

            IMapChunk mapchunk = chunks[0].MapChunk;

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

            if (radius <= 0)
            {
                return(SubDepositsToPlace);
            }

            // Let's deform that perfect circle a bit (+/- 25%)
            float deform  = GameMath.Clamp(depositRand.NextFloat() - 0.5f, -0.25f, 0.25f);
            int   radiusX = radius - (int)(radius * deform);
            int   radiusZ = radius + (int)(radius * deform);
            int   posY;

            // No need to caluclate further if this deposit won't be part of this chunk
            if (radiusX + offsetX < 0 || radiusZ + offsetZ < 0 || offsetX - radiusX >= chunksize || offsetZ - radiusZ >= chunksize)
            {
                return(SubDepositsToPlace);
            }


            IMapChunk originMapchunk = null;
            int       origPosY       = 0;

            int lx = GameMath.Mod(offsetX, chunksize);
            int lz = GameMath.Mod(offsetZ, chunksize);

            if (variant.MaxY < 1 || variant.CheckClimate)
            {
                originMapchunk = api.WorldManager.GetMapChunk((chunkX * chunksize + offsetX) / chunksize, (chunkZ * chunksize + offsetZ) / chunksize);
                if (originMapchunk == null)
                {
                    return(SubDepositsToPlace);                        // argh >.<
                }
                origPosY = originMapchunk.RainHeightMap[lz * chunksize + lx];
                if ((float)origPosY / api.World.BlockAccessor.MapSizeY > variant.MaxY)
                {
                    return(SubDepositsToPlace);
                }
            }



            // Check if suited for this area, climate wise
            if (variant.CheckClimate)
            {
                IntMap climateMap = api.World.BlockAccessor.GetMapRegion((chunkX * chunksize + offsetX) / regionSize, (chunkZ * chunksize + offsetZ) / regionSize).ClimateMap;

                float posXInRegionClimate = ((float)lx / regionSize - lx / regionSize) * noiseSizeClimate;
                float posZInRegionClimate = ((float)lz / regionSize - lz / regionSize) * noiseSizeClimate;

                int   climate = climateMap.GetUnpaddedColorLerped(posXInRegionClimate, posZInRegionClimate);
                float temp    = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, origPosY - TerraGenConfig.seaLevel);
                float rainRel = TerraGenConfig.GetRainFall((climate >> 8) & 0xff, origPosY) / 255f;

                if (rainRel < variant.MinRain || rainRel > variant.MaxRain || temp < variant.MinTemp || temp > variant.MaxTemp)
                {
                    return(SubDepositsToPlace);
                }
            }


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

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

            int  blockIndex    = 0;
            bool parentBlockOk = false;

            float depthf;

            bool shouldGenSurfaceDeposit = depositRand.NextFloat() > 0.35f && variant.SurfaceBlockCode != null;

            if (forceInitialPosY != null)
            {
                depthf = (float)forceInitialPosY / mapchunk.WorldGenTerrainHeightMap[offsetX * chunksize + offsetZ];
            }
            else
            {
                depthf = variant.Depth.nextFloat(1, depositRand);
            }

            int depthi = (int)depthf;

            int topLeft  = 2 * depositRand.NextInt(radiusX + 1) - radiusX;
            int topRight = 2 * depositRand.NextInt(radiusZ + 1) - radiusZ;
            int botLeft  = 2 * depositRand.NextInt(radiusX + 1) - radiusX;
            int botRight = 2 * depositRand.NextInt(radiusZ + 1) - radiusZ;
            int yOff     = 0;

            // Only generate inside this current chunk column
            int minx = GameMath.Clamp(offsetX - radiusX, 0, chunksize);
            int maxx = GameMath.Clamp(offsetX + radiusX, 0, chunksize);
            int minz = GameMath.Clamp(offsetZ - radiusZ, 0, chunksize);
            int maxz = GameMath.Clamp(offsetZ + radiusZ, 0, chunksize);

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

            for (int x = minx; x < maxx; x++)
            {
                float xSq = (x - offsetX) * (x - offsetX) * xRadSqInv;
                for (int z = minz; z < maxz; z++)
                {
                    if (xSq + (z - offsetZ) * (z - offsetZ) * zRadSqInv > 1)
                    {
                        continue;
                    }

                    if (variant.Placement == EnumDepositPlacement.FollowSurfaceBelow)
                    {
                        posY = mapchunk.WorldGenTerrainHeightMap[z * chunksize + x] - depthi;
                    }
                    else if (variant.Placement == EnumDepositPlacement.FollowSurface)
                    {
                        yOff = (int)GameMath.BiLerp(topLeft, topRight, botLeft, botRight, (x - offsetX + radiusX) / (2f * radiusX), (z - offsetZ + radiusZ) / (2f * radiusZ));

                        posY = (int)(depthf * mapchunk.WorldGenTerrainHeightMap[z * chunksize + x]) + yOff / 2;
                    }
                    else if (variant.Placement == EnumDepositPlacement.Straight)
                    {
                        posY = (int)(depthf * mapchunk.WorldGenTerrainHeightMap[z * chunksize + x]);
                    }
                    else
                    {
                        yOff = (int)GameMath.BiLerp(topLeft, topRight, botLeft, botRight, (x - offsetX + radiusX) / (2f * radiusX), (z - offsetZ + radiusZ) / (2f * radiusZ));

                        posY = depthi + yOff;
                    }

                    // Some deposits may not appear all over cliffs
                    if (variant.CheckClimate && Math.Abs(origPosY - posY) > variant.MaxYRoughness)
                    {
                        continue;
                    }

                    for (int y = 0; y < thickness; y++)
                    {
                        if (posY <= 1 || posY >= worldheight)
                        {
                            continue;
                        }

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

                        // Check if we are in mother material, but only if it has changed since last iteration (should reduce amount of these checks by 50-100%)
                        parentBlockOk = false;
                        for (int i = 0; i < variant.ParentBlockIds.Length; i++)
                        {
                            if (variant.ParentBlockIds[i] == blockId)
                            {
                                parentBlockOk = true;
                                blockIndex    = i;
                                break;
                            }
                        }

                        if (parentBlockOk)
                        {
                            if (variant.WithBlockCallback)
                            {
                                tmpPos.Set(chunkX * chunksize + x, posY, chunkZ * chunksize + z);
                                blockTypes[variant.BlockIds[blockIndex]].TryPlaceBlockForWorldGen(blockAccessor, tmpPos, BlockFacing.UP);
                            }
                            else
                            {
                                chunks[posY / chunksize].Blocks[index3d] = variant.BlockIds[blockIndex];
                            }


                            for (int i = 0; i < variant.ChildDeposits.Length; i++)
                            {
                                float rndVal   = depositRand.NextFloat();
                                float quantity = variant.ChildDeposits[i].Quantity * invChunkAreaSize;

                                if (quantity > rndVal)
                                {
                                    Vec3i pos = new Vec3i(x, posY, z);

                                    if (ShouldPlaceAdjustedForOreMap(variant.ChildDeposits[i], chunkX * chunksize + x, chunkZ * chunksize + z, quantity, rndVal))
                                    {
                                        SubDepositsToPlace[pos] = variant.ChildDeposits[i];
                                    }
                                }
                            }

                            if (shouldGenSurfaceDeposit)
                            {
                                int   surfaceY = mapchunk.RainHeightMap[z * chunksize + x];
                                int   depth    = surfaceY - posY;
                                float chance   = variant.SurfaceBlockChance * Math.Max(0, 1 - depth / 8f);
                                if (depositRand.NextFloat() < chance)
                                {
                                    index3d = (((surfaceY + 1) % chunksize) * chunksize + z) * chunksize + x;

                                    Block belowBlock = api.World.Blocks[chunks[surfaceY / chunksize].Blocks[((surfaceY % chunksize) * chunksize + z) * chunksize + x]];

                                    if (belowBlock.SideSolid[BlockFacing.UP.Index] && chunks[(surfaceY + 1) / chunksize].Blocks[index3d] == 0)
                                    {
                                        chunks[(surfaceY + 1) / chunksize].Blocks[index3d] = variant.SurfaceBlockIds[blockIndex];
                                    }
                                }
                            }
                        }

                        posY--;
                    }
                }
            }

            return(SubDepositsToPlace);
        }
Пример #29
0
        private void OnChunkColumnGeneration(IServerChunk[] chunks, int chunkX, int chunkZ)
        {
            IntMap forestMap  = chunks[0].MapChunk.MapRegion.ForestMap;
            IntMap climateMap = chunks[0].MapChunk.MapRegion.ClimateMap;

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

            int regionChunkSize = api.WorldManager.RegionSize / chunksize;
            int rlX             = chunkX % regionChunkSize;
            int rlZ             = chunkZ % regionChunkSize;

            // "Pixels per chunk"
            float facF = (float)forestMap.InnerSize / regionChunkSize;

            // Retrieves the map data on the chunk edges
            int forestUpLeft   = forestMap.GetUnpaddedInt((int)(rlX * facF), (int)(rlZ * facF));
            int forestUpRight  = forestMap.GetUnpaddedInt((int)(rlX * facF + facF), (int)(rlZ * facF));
            int forestBotLeft  = forestMap.GetUnpaddedInt((int)(rlX * facF), (int)(rlZ * facF + facF));
            int forestBotRight = forestMap.GetUnpaddedInt((int)(rlX * facF + facF), (int)(rlZ * facF + facF));

            float facC            = (float)climateMap.InnerSize / regionChunkSize;
            int   climateUpLeft   = climateMap.GetUnpaddedInt((int)(rlX * facC), (int)(rlZ * facC));
            int   climateUpRight  = climateMap.GetUnpaddedInt((int)(rlX * facC + facC), (int)(rlZ * facC));
            int   climateBotLeft  = climateMap.GetUnpaddedInt((int)(rlX * facC), (int)(rlZ * facC + facC));
            int   climateBotRight = climateMap.GetUnpaddedInt((int)(rlX * facC + facC), (int)(rlZ * facC + facC));



            for (int x = 0; x < chunksize; x++)
            {
                for (int z = 0; z < chunksize; z++)
                {
                    int posY = heightMap[z * chunksize + x];

                    int   climate      = GameMath.BiLerpRgbColor((float)x / chunksize, (float)z / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
                    int   tempUnscaled = (climate >> 16) & 0xff;
                    float temp         = TerraGenConfig.GetScaledAdjustedTemperatureFloat(tempUnscaled, posY - TerraGenConfig.seaLevel);
                    float rainRel      = TerraGenConfig.GetRainFall((climate >> 8) & 0xff, posY) / 255f;
                    float forestRel    = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)x / chunksize, (float)z / chunksize) / 255f;

                    int prevY = posY;

                    posY = PutLayers(x, posY, z, chunks, rainRel, temp, tempUnscaled, heightMap);
                    PlaceTallGrass(x, prevY, z, chunks, rainRel, temp, forestRel);


                    // Try again to put layers if above sealevel and we found over 10 air blocks
                    int foundAir = 0;
                    while (posY >= TerraGenConfig.seaLevel - 1)
                    {
                        int    chunkY  = posY / chunksize;
                        int    lY      = posY % chunksize;
                        int    index3d = (chunksize * lY + z) * chunksize + x;
                        ushort blockId = chunks[chunkY].Blocks[index3d];

                        if (blockId == 0)
                        {
                            foundAir++;
                        }
                        else
                        {
                            if (foundAir >= 8)
                            {
                                temp    = TerraGenConfig.GetScaledAdjustedTemperatureFloat(tempUnscaled, posY - TerraGenConfig.seaLevel);
                                rainRel = TerraGenConfig.GetRainFall((climate >> 8) & 0xff, posY) / 255f;

                                PutLayers(x, posY, z, chunks, rainRel, temp, tempUnscaled, null);
                                break;
                            }
                            else
                            {
                                foundAir = 0;
                            }
                        }

                        posY--;
                    }
                }
            }
        }
        void genTrees(int chunkX, int chunkZ)
        {
            int   triesTrees = (int)treeSupplier.treeGenProps.treesPerChunk.nextFloat();
            int   dx, dz, x, z;
            Block block;

            while (triesTrees > 0)
            {
                triesTrees--;

                dx = rnd.Next(chunksize);
                dz = rnd.Next(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);
                if (block.Fertility == 0)
                {
                    continue;
                }

                // Place according to forest value
                float treeDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)dx / chunksize, (float)dz / chunksize);
                int   climate     = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
                float shrubChance = GameMath.BiLerp(shrubUpLeft, shrubUpRight, shrubBotLeft, shrubBotRight, (float)dx / chunksize, (float)dz / chunksize);

                float treeDensityNormalized = treeDensity / 255f;


                // 1 in 400 chance to always spawn a tree
                // otherwise go by tree density using a quadratic drop off to create clearer forest edges
                if (rnd.NextDouble() > Math.Max(0.0025, treeDensityNormalized * treeDensityNormalized))
                {
                    continue;
                }
                TreeGenForClimate treegenParams = treeSupplier.GetRandomTreeGenForClimate(climate, (int)treeDensity, y);

                if (treegenParams != null)
                {
                    bool canGen = true;
                    for (int i = 0; i < structuresIntersectingChunk.Count; i++)
                    {
                        if (structuresIntersectingChunk[i].Location.Contains(tmpPos))
                        {
                            canGen = false; break;
                        }
                    }
                    if (!canGen)
                    {
                        continue;
                    }

                    if (blockAccessor.GetBlock(tmpPos.X, tmpPos.Y, tmpPos.Z).Replaceable >= 6000)
                    {
                        tmpPos.Y--;
                    }

                    treegenParams.treeGen.GrowTree(
                        blockAccessor,
                        tmpPos,
                        treegenParams.size,
                        treegenParams.vinesGrowthChance,
                        treeDensityNormalized
                        );
                }
            }
        }