private void OnChunkColumnGen(IServerChunk[] chunks, int chunkX, int chunkZ) { if (!TerraGenConfig.GenerateStructures) { return; } IMapRegion region = chunks[0].MapChunk.MapRegion; IntMap forestMap = region.ForestMap; IntMap climateMap = region.ClimateMap; int rlX = chunkX % regionChunkSize; int rlZ = chunkZ % regionChunkSize; // A region has 16 chunks // Size of the forest map is RegionSize / TerraGenConfig.forestMapScale => 32*16 / 32 = 16 pixel // rlX, rlZ goes from 0..16 pixel // facF = 16/16 = 1 // Get 4 pixels for chunkx, chunkz, chunkx+1 and chunkz+1 inside the map float facF = (float)forestMap.InnerSize / regionChunkSize; forestUpLeft = forestMap.GetUnpaddedInt((int)(rlX * facF), (int)(rlZ * facF)); forestUpRight = forestMap.GetUnpaddedInt((int)(rlX * facF + facF), (int)(rlZ * facF)); forestBotLeft = forestMap.GetUnpaddedInt((int)(rlX * facF), (int)(rlZ * facF + facF)); forestBotRight = forestMap.GetUnpaddedInt((int)(rlX * facF + facF), (int)(rlZ * facF + facF)); float facC = (float)climateMap.InnerSize / regionChunkSize; climateUpLeft = climateMap.GetUnpaddedInt((int)(rlX * facC), (int)(rlZ * facC)); climateUpRight = climateMap.GetUnpaddedInt((int)(rlX * facC + facC), (int)(rlZ * facC)); climateBotLeft = climateMap.GetUnpaddedInt((int)(rlX * facC), (int)(rlZ * facC + facC)); climateBotRight = climateMap.GetUnpaddedInt((int)(rlX * facC + facC), (int)(rlZ * facC + facC)); heightmap = chunks[0].MapChunk.WorldGenTerrainHeightMap; BlockPos pos = new BlockPos(); for (int i = 0; i < scfg.Structures.Length; i++) { WorldGenStructure struc = scfg.Structures[i]; float chance = struc.Chance * scfg.ChanceMultiplier; while (chance-- > rnd.NextDouble()) { int dx = rnd.Next(chunksize); int dz = rnd.Next(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(), chunkZ * chunksize + dz); } else { pos.Set(chunkX * chunksize + dx, 8 + rnd.Next(ySurface - 8 - 5), chunkZ * chunksize + dz); } } else { pos.Set(chunkX * chunksize + dx, ySurface, chunkZ * chunksize + dz); } struc.TryGenerate(worldgenBlockAccessor, api.World, pos, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); } } }
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--; } } } }