public void initWorldGen(int seedDiff) { IAsset asset = api.Assets.Get("worldgen/rockstrata.json"); strata = asset.ToObject <RockStrataConfig>(); for (int i = 0; i < strata.Variants.Length; i++) { strata.Variants[i].Init(api.World); } LoadGlobalConfig(api); chunksize = api.WorldManager.ChunkSize; regionSize = api.WorldManager.RegionSize; chunkRatio = (float)chunksize / regionSize; // Unpadded region noise size in chunks regionChunkSize = regionSize / chunksize; rand = new Random(api.WorldManager.Seed + seedDiff); // Unpadded region noise size in blocks int geoProvRegionNoiseSize = regionSize / TerraGenConfig.geoProvMapScale; // Amount of regions in all of the map regionMapSize = api.WorldManager.MapSizeX / (chunksize * geoProvRegionNoiseSize); rockBlockId = (ushort)api.WorldManager.GetBlockId(new AssetLocation("rock-granite")); worldHeight = api.WorldManager.MapSizeY; distort2dx = new SimplexNoise(new double[] { 14, 9, 6, 3 }, new double[] { 1 / 100.0, 1 / 50.0, 1 / 25.0, 1 / 12.5 }, api.World.SeaLevel + 9876 + seedDiff); distort2dz = new SimplexNoise(new double[] { 14, 9, 6, 3 }, new double[] { 1 / 100.0, 1 / 50.0, 1 / 25.0, 1 / 12.5 }, api.World.SeaLevel + 9877 + seedDiff); strataNoises = new MapLayerCustomPerlin[strata.Variants.Length]; for (int i = 0; i < strataNoises.Length; i++) { RockStratum stratum = strata.Variants[i]; double[] ampls = (double[])stratum.Amplitudes.Clone(); double[] freq = (double[])stratum.Frequencies.Clone(); double[] th = (double[])stratum.Thresholds.Clone(); if (ampls.Length != freq.Length || ampls.Length != th.Length) { throw new ArgumentException(string.Format("Bug in Rock stratum {0}: The list of amplitudes ({1} elements), frequencies ({2} elements) and thresholds ({3} elements) are not of the same length!", i, ampls.Length, freq.Length, th.Length)); } for (int j = 0; j < freq.Length; j++) { freq[j] /= TerraGenConfig.rockStrataOctaveScale; ampls[j] *= api.WorldManager.MapSizeY; th[j] *= api.WorldManager.MapSizeY; } strataNoises[i] = new MapLayerCustomPerlin(api.World.Seed + 23423 + i + seedDiff, ampls, freq, th); } }
public void preLoad(IServerChunk[] chunks, int chunkX, int chunkZ) { mapChunk = chunks[0].MapChunk; heightMap = mapChunk.WorldGenTerrainHeightMap; rdx = chunkX % regionChunkSize; rdz = chunkZ % regionChunkSize; stratum = null; step = 0; strataThickness = 0; map = GetOrLoadLerpedProvinceMap(chunks[0].MapChunk, chunkX, chunkZ); lerpMapInv = 1f / TerraGenConfig.geoProvMapScale; chunkInRegionX = (chunkX % regionChunkSize) * lerpMapInv * chunksize; chunkInRegionZ = (chunkZ % regionChunkSize) * lerpMapInv * chunksize; provinces = NoiseGeoProvince.provinces; grp = 0; }
void ReadPos(IServerPlayer player, CmdArgs arguments) { if (arguments.Length < 2) { player.SendMessage(groupId, "/wgen pos [gprov|landform|climate|height]", EnumChatType.CommandError); return; } int chunkSize = api.WorldManager.ChunkSize; BlockPos pos = player.Entity.Pos.AsBlockPos; IServerChunk serverchunk = api.WorldManager.GetChunk(pos); if (serverchunk == null) { player.SendMessage(groupId, "Can't check here, beyond chunk boundaries!", EnumChatType.CommandError); return; } IMapRegion mapRegion = serverchunk.MapChunk.MapRegion; IMapChunk mapchunk = serverchunk.MapChunk; int regionChunkSize = api.WorldManager.RegionSize / chunkSize; int lx = pos.X % chunkSize; int lz = pos.Z % chunkSize; int chunkX = pos.X / chunkSize; int chunkZ = pos.Z / chunkSize; int regionX = pos.X / regionSize; int regionZ = pos.Z / regionSize; switch (arguments[1]) { case "coords": player.SendMessage(groupId, string.Format("Chunk X/Z: {0}/{1}, Region X/Z: {2},{3}", chunkX, chunkZ, regionX, regionZ), EnumChatType.CommandSuccess); break; case "structures": bool found = false; api.World.BlockAccessor.WalkStructures(pos, (struc) => { found = true; player.SendMessage(groupId, "Structure with code " + struc.Code + " at this position", EnumChatType.CommandSuccess); }); if (!found) { player.SendMessage(groupId, "No structures at this position", EnumChatType.CommandSuccess); } return; case "height": { string str = string.Format("Rain y={0}, Worldgen terrain y={1}", serverchunk.MapChunk.RainHeightMap[lz * chunkSize + lx], serverchunk.MapChunk.WorldGenTerrainHeightMap[lz * chunkSize + lx]); player.SendMessage(groupId, str, EnumChatType.CommandSuccess); } break; case "cavedistort": Bitmap bmp = new Bitmap(chunkSize, chunkSize); for (int x = 0; x < chunkSize; x++) { for (int z = 0; z < chunkSize; z++) { byte color = mapchunk.CaveHeightDistort[z * chunkSize + x]; bmp.SetPixel(x, z, Color.FromArgb((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff)); } } bmp.Save("cavedistort" + chunkX + "-" + chunkZ + ".png"); player.SendMessage(groupId, "saved bitmap cavedistort" + chunkX + "-" + chunkZ + ".png", EnumChatType.CommandSuccess); break; case "gprov": { int noiseSizeGeoProv = mapRegion.GeologicProvinceMap.InnerSize; float posXInRegion = ((float)pos.X / regionSize - regionX) * noiseSizeGeoProv; float posZInRegion = ((float)pos.Z / regionSize - regionZ) * noiseSizeGeoProv; GeologicProvinceVariant[] provincesByIndex = NoiseGeoProvince.provinces.Variants; IntMap intmap = mapRegion.GeologicProvinceMap; LerpedWeightedIndex2DMap map = new LerpedWeightedIndex2DMap(intmap.Data, mapRegion.GeologicProvinceMap.Size, TerraGenConfig.geoProvSmoothingRadius, mapRegion.GeologicProvinceMap.TopLeftPadding, mapRegion.GeologicProvinceMap.BottomRightPadding); WeightedIndex[] indices = map[posXInRegion, posZInRegion]; string text = ""; foreach (WeightedIndex windex in indices) { if (text.Length > 0) { text += ", "; } text += (100 * windex.Weight).ToString("#.#") + "% " + provincesByIndex[windex.Index].Code; } player.SendMessage(groupId, text, EnumChatType.CommandSuccess); break; } case "rockstrata": { GenRockStrataNew rockstratagen = api.ModLoader.GetModSystem <GenRockStrataNew>(); int noiseSizeGeoProv = mapRegion.GeologicProvinceMap.InnerSize; float posXInRegion = ((float)pos.X / regionSize - pos.X / regionSize) * noiseSizeGeoProv; float posZInRegion = ((float)pos.Z / regionSize - pos.Z / regionSize) * noiseSizeGeoProv; GeologicProvinceVariant[] provincesByIndex = NoiseGeoProvince.provinces.Variants; IntMap intmap = mapRegion.GeologicProvinceMap; LerpedWeightedIndex2DMap map = new LerpedWeightedIndex2DMap(intmap.Data, mapRegion.GeologicProvinceMap.Size, TerraGenConfig.geoProvSmoothingRadius, mapRegion.GeologicProvinceMap.TopLeftPadding, mapRegion.GeologicProvinceMap.BottomRightPadding); WeightedIndex[] indices = map[posXInRegion, posZInRegion]; float[] rockGroupMaxThickness = new float[4]; rockGroupMaxThickness[0] = rockGroupMaxThickness[1] = rockGroupMaxThickness[2] = rockGroupMaxThickness[3] = 0; int rdx = chunkX % regionChunkSize; int rdz = chunkZ % regionChunkSize; IntMap rockMap; float step = 0; float distx = (float)rockstratagen.distort2dx.Noise(pos.X, pos.Z); float distz = (float)rockstratagen.distort2dz.Noise(pos.X, pos.Z); for (int i = 0; i < indices.Length; i++) { float w = indices[i].Weight; GeologicProvinceVariant var = NoiseGeoProvince.provinces.Variants[indices[i].Index]; rockGroupMaxThickness[0] += var.RockStrataIndexed[0].MaxThickness * w; rockGroupMaxThickness[1] += var.RockStrataIndexed[1].MaxThickness * w; rockGroupMaxThickness[2] += var.RockStrataIndexed[2].MaxThickness * w; rockGroupMaxThickness[3] += var.RockStrataIndexed[3].MaxThickness * w; } System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.AppendLine("Sedimentary max thickness: " + rockGroupMaxThickness[(int)EnumRockGroup.Sedimentary]); sb.AppendLine("Metamorphic max thickness: " + rockGroupMaxThickness[(int)EnumRockGroup.Metamorphic]); sb.AppendLine("Igneous max thickness: " + rockGroupMaxThickness[(int)EnumRockGroup.Igneous]); sb.AppendLine("Volcanic max thickness: " + rockGroupMaxThickness[(int)EnumRockGroup.Volcanic]); sb.AppendLine("========"); for (int id = 0; id < rockstratagen.strata.Variants.Length; id++) { rockMap = mapchunk.MapRegion.RockStrata[id]; step = (float)rockMap.InnerSize / regionChunkSize; float dist = 1 + GameMath.Clamp((distx + distz) / 30, 0.9f, 1.1f); sb.AppendLine(rockstratagen.strata.Variants[id].BlockCode.ToShortString() + " max thickness: " + rockMap.GetIntLerpedCorrectly(rdx * step + step * (float)(lx + distx) / chunkSize, rdz * step + step * (float)(lz + distz) / chunkSize)); } sb.AppendLine("======"); int surfaceY = api.World.BlockAccessor.GetTerrainMapheightAt(pos); int ylower = 1; int yupper = surfaceY; int rockStrataId = -1; float strataThickness = 0; RockStratum stratum = null; OrderedDictionary <int, int> stratathicknesses = new OrderedDictionary <int, int>(); while (ylower <= yupper) { if (--strataThickness <= 0) { rockStrataId++; if (rockStrataId >= rockstratagen.strata.Variants.Length) { break; } stratum = rockstratagen.strata.Variants[rockStrataId]; rockMap = mapchunk.MapRegion.RockStrata[rockStrataId]; step = (float)rockMap.InnerSize / regionChunkSize; int grp = (int)stratum.RockGroup; float dist = 1 + GameMath.Clamp((distx + distz) / 30, 0.9f, 1.1f); strataThickness = Math.Min(rockGroupMaxThickness[grp] * dist, rockMap.GetIntLerpedCorrectly(rdx * step + step * (float)(lx + distx) / chunkSize, rdz * step + step * (float)(lz + distz) / chunkSize)); strataThickness -= (stratum.RockGroup == EnumRockGroup.Sedimentary) ? Math.Max(0, yupper - TerraGenConfig.seaLevel) * 0.5f : 0; if (strataThickness < 2) { strataThickness = -1; continue; } } if (!stratathicknesses.ContainsKey(stratum.BlockId)) { stratathicknesses[stratum.BlockId] = 0; } stratathicknesses[stratum.BlockId]++; if (stratum.GenDir == EnumStratumGenDir.BottomUp) { ylower++; } else { yupper--; } } foreach (var val in stratathicknesses) { sb.AppendLine(api.World.Blocks[val.Key].Code.ToShortString() + " : " + val.Value + " blocks"); } player.SendMessage(groupId, sb.ToString(), EnumChatType.CommandSuccess); break; } case "landform": { int noiseSizeLandform = mapRegion.LandformMap.InnerSize; float posXInRegion = ((float)pos.X / regionSize - pos.X / regionSize) * noiseSizeLandform; float posZInRegion = ((float)pos.Z / regionSize - pos.Z / regionSize) * noiseSizeLandform; LandformVariant[] landforms = NoiseLandforms.landforms.LandFormsByIndex; IntMap intmap = mapRegion.LandformMap; LerpedWeightedIndex2DMap map = new LerpedWeightedIndex2DMap(intmap.Data, mapRegion.LandformMap.Size, TerraGenConfig.landFormSmoothingRadius, intmap.TopLeftPadding, intmap.BottomRightPadding); WeightedIndex[] indices = map[posXInRegion, posZInRegion]; string text = ""; foreach (WeightedIndex windex in indices) { if (text.Length > 0) { text += ", "; } text += (100 * windex.Weight).ToString("#.#") + "% " + landforms[windex.Index].Code; } player.SendMessage(groupId, text, EnumChatType.CommandSuccess); break; } case "climate": { ClimateCondition climate = api.World.BlockAccessor.GetClimateAt(pos); string text = string.Format("Temperature: {0}°, Rainfall: {1}%, Fertility: {2}%, Forest: {3}%, Shrub: {4}%, Sealevel dist: {5}%", climate.Temperature.ToString("0.#"), (int)(climate.Rainfall * 100f), (int)(climate.Fertility * 100f), (int)(climate.ForestDensity * 100f), (int)(climate.ShrubDensity * 100f), (int)(100f * pos.Y / 255f)); player.SendMessage(groupId, text, EnumChatType.CommandSuccess); break; } } }
public void genBlockColumn(IServerChunk[] chunks, int chunkX, int chunkZ, int lx, int lz) { int surfaceY = heightMap[lz * chunksize + lx]; int ylower = 1; int yupper = surfaceY; strataThickness = 0; WeightedIndex[] indices = map[ chunkInRegionX + lx * lerpMapInv, chunkInRegionZ + lz * lerpMapInv ]; rockGroupMaxThickness[0] = rockGroupMaxThickness[1] = rockGroupMaxThickness[2] = rockGroupMaxThickness[3] = 0; rockGroupCurrentThickness[0] = rockGroupCurrentThickness[1] = rockGroupCurrentThickness[2] = rockGroupCurrentThickness[3] = 0; for (int i = 0; i < indices.Length; i++) { float w = indices[i].Weight; GeologicProvinceVariant var = provinces.Variants[indices[i].Index]; rockGroupMaxThickness[0] += var.RockStrataIndexed[0].MaxThickness * w; rockGroupMaxThickness[1] += var.RockStrataIndexed[1].MaxThickness * w; rockGroupMaxThickness[2] += var.RockStrataIndexed[2].MaxThickness * w; rockGroupMaxThickness[3] += var.RockStrataIndexed[3].MaxThickness * w; } float distx = (float)distort2dx.Noise(chunkX * chunksize + lx, chunkZ * chunksize + lz); float distz = (float)distort2dz.Noise(chunkX * chunksize + lx, chunkZ * chunksize + lz); rockStrataId = -1; while (ylower <= yupper) { if (--strataThickness <= 0) { rockStrataId++; if (rockStrataId >= strata.Variants.Length) { break; } stratum = strata.Variants[rockStrataId]; rockMap = mapChunk.MapRegion.RockStrata[rockStrataId]; step = (float)rockMap.InnerSize / regionChunkSize; grp = (int)stratum.RockGroup; float thicknessDistort = GameMath.Clamp((distx + distz) / 30, 0.9f, 1.1f); float allowedThickness = rockGroupMaxThickness[grp] * thicknessDistort - rockGroupCurrentThickness[grp]; strataThickness = Math.Min(allowedThickness, rockMap.GetIntLerpedCorrectly(rdx * step + step * (float)(lx + distx) / chunksize, rdz * step + step * (float)(lz + distz) / chunksize)); strataThickness -= (stratum.RockGroup == EnumRockGroup.Sedimentary) ? Math.Max(0, yupper - TerraGenConfig.seaLevel) * 0.5f : 0; if (strataThickness < 2) { strataThickness = -1; continue; } } rockGroupCurrentThickness[grp]++; if (stratum.GenDir == EnumStratumGenDir.BottomUp) { int chunkY = ylower / chunksize; int lY = ylower - chunkY * chunksize; int localIndex3D = (chunksize * lY + lz) * chunksize + lx; if (chunks[chunkY].Blocks[localIndex3D] == rockBlockId) { chunks[chunkY].Blocks[localIndex3D] = stratum.BlockId; } ylower++; } else { int chunkY = yupper / chunksize; int lY = yupper - chunkY * chunksize; int localIndex3D = (chunksize * lY + lz) * chunksize + lx; if (chunks[chunkY].Blocks[localIndex3D] == rockBlockId) { chunks[chunkY].Blocks[localIndex3D] = stratum.BlockId; } yupper--; } } }