public DepositVariant Clone() { DepositVariant var = new DepositVariant() { fromFile = fromFile, Code = Code, TriesPerChunk = TriesPerChunk, Generator = Generator, WithOreMap = WithOreMap, WithBlockCallback = WithBlockCallback, Attributes = Attributes?.Clone(), Climate = Climate?.Clone(), ChildDeposits = ChildDeposits == null ? null : (DepositVariant[])ChildDeposits.Clone(), OreMapLayer = OreMapLayer, }; foreach (var val in ChildDeposits) { val.parentDeposit = var; } var.GeneratorInst = DepositGeneratorRegistry.CreateGenerator(Generator, Attributes, api, var, GeneratorInst.DepositRand, GeneratorInst.DistortNoiseGen); return(var); }
private void OnMapRegionGen(IMapRegion mapRegion, int regionX, int regionZ) { IntMap map; for (int i = 0; i < deposits.variants.Length; i++) { DepositVariant variant = deposits.variants[i]; if (variant.OreMap != null) { map = new IntMap(); map.Size = noiseSizeOre + 1; map.BottomRightPadding = 1; map.Data = variant.OreMap.GenLayer(regionX * noiseSizeOre, regionZ * noiseSizeOre, noiseSizeOre + 1, noiseSizeOre + 1); mapRegion.OreMaps[variant.Code] = map; } if (variant.ChildDeposits != null) { for (int k = 0; k < variant.ChildDeposits.Length; k++) { DepositVariant childVariant = variant.ChildDeposits[k]; if (childVariant.OreMap != null) { map = new IntMap(); map.Size = noiseSizeOre + 1; map.BottomRightPadding = 1; map.Data = childVariant.OreMap.GenLayer(regionX * noiseSizeOre, regionZ * noiseSizeOre, noiseSizeOre + 1, noiseSizeOre + 1); mapRegion.OreMaps[childVariant.Code] = map; } } } } }
public void OnMapRegionGen(IMapRegion mapRegion, int regionX, int regionZ) { IntDataMap2D map; if (OreMapLayer != null && !mapRegion.OreMaps.ContainsKey(Code)) { map = new IntDataMap2D(); map.Size = noiseSizeOre + 1; map.BottomRightPadding = 1; map.Data = OreMapLayer.GenLayer(regionX * noiseSizeOre, regionZ * noiseSizeOre, noiseSizeOre + 1, noiseSizeOre + 1); mapRegion.OreMaps[Code] = map; } if (ChildDeposits != null) { for (int k = 0; k < ChildDeposits.Length; k++) { DepositVariant childVariant = ChildDeposits[k]; if (childVariant.OreMapLayer != null && !mapRegion.OreMaps.ContainsKey(childVariant.Code)) { map = new IntDataMap2D(); map.Size = noiseSizeOre + 1; map.BottomRightPadding = 1; map.Data = childVariant.OreMapLayer.GenLayer(regionX * noiseSizeOre, regionZ * noiseSizeOre, noiseSizeOre + 1, noiseSizeOre + 1); mapRegion.OreMaps[childVariant.Code] = map; } } } }
public void OnMapRegionGen(IMapRegion mapRegion, int regionX, int regionZ) { int pad = 2; TerraGenConfig.depositVerticalDistortScale = 2; int noiseSize = api.WorldManager.RegionSize / TerraGenConfig.depositVerticalDistortScale; IntDataMap2D map = mapRegion.OreMapVerticalDistortBottom; map.Size = noiseSize + 2 * pad; map.BottomRightPadding = map.TopLeftPadding = pad; map.Data = verticalDistortBottom.GenLayer(regionX * noiseSize - pad, regionZ * noiseSize - pad, noiseSize + 2 * pad, noiseSize + 2 * pad); map = mapRegion.OreMapVerticalDistortTop; map.Size = noiseSize + 2 * pad; map.BottomRightPadding = map.TopLeftPadding = pad; map.Data = verticalDistortTop.GenLayer(regionX * noiseSize - pad, regionZ * noiseSize - pad, noiseSize + 2 * pad, noiseSize + 2 * pad); for (int i = 0; i < Deposits.Length; i++) { DepositVariant variant = Deposits[i]; variant.OnMapRegionGen(mapRegion, regionX, regionZ); } }
private bool ShouldPlaceAdjustedForOreMap(DepositVariant variant, int posX, int posZ, float quantity, float rndVal) { if (!variant.WithOreMap) { return(true); } float quantityFactor = 1; IMapRegion originMapRegion = api.WorldManager.GetMapRegion((posX) / regionSize, (posZ) / regionSize); if (originMapRegion == null) { return(false); } int lx = posX % regionSize; int lz = posZ % regionSize; IntMap map = null; originMapRegion.OreMaps.TryGetValue(variant.Code, out map); if (map != null) { float posXInRegionOre = (float)lx / regionSize * noiseSizeOre; float posZInRegionOre = (float)lz / regionSize * noiseSizeOre; int oreDist = originMapRegion.OreMaps[variant.Code].GetUnpaddedColorLerped(posXInRegionOre, posZInRegionOre); quantityFactor = (oreDist & 0xff) / 255f; } return(quantity * quantityFactor > rndVal); }
internal override void GeneratePartial(IServerChunk[] chunks, int intoChunkX, int intoChunkZ, int fromChunkdX, int fromChunkdZ) { for (int i = 0; i < deposits.variants.Length; i++) { DepositVariant variant = deposits.variants[i]; float quantityFactor = 1; int originChunkX = intoChunkX + fromChunkdX; int originChunkZ = intoChunkZ + fromChunkdZ; if (variant.WithOreMap) { IMapRegion originMapRegion = api.WorldManager.GetMapRegion((originChunkX * chunksize) / regionSize, (originChunkZ * chunksize) / regionSize); if (originMapRegion == null) { continue; } int lx = (originChunkX * chunksize + chunksize / 2) % regionSize; int lz = (originChunkZ * chunksize + chunksize / 2) % regionSize; IntMap map = null; originMapRegion.OreMaps.TryGetValue(variant.Code, out map); if (map != null) { float posXInRegionOre = GameMath.Clamp((float)lx / regionSize * noiseSizeOre, 0, noiseSizeOre - 1); float posZInRegionOre = GameMath.Clamp((float)lz / regionSize * noiseSizeOre, 0, noiseSizeOre - 1); int oreDist = originMapRegion.OreMaps[variant.Code].GetUnpaddedColorLerped(posXInRegionOre, posZInRegionOre); quantityFactor = (oreDist & 0xff) / 255f; } } float qModified = variant.Quantity * quantityFactor; int quantity = (int)qModified; quantity += chunkRand.NextInt(100) < 100 * (qModified - quantity) ? 1 : 0; while (quantity-- > 0) { int offsetX = chunksize * fromChunkdX + chunkRand.NextInt(chunksize); int offsetZ = chunksize * fromChunkdZ + chunkRand.NextInt(chunksize); depositRand.SetWorldSeed(chunkRand.NextInt(10000000)); depositRand.InitPositionSeed(intoChunkX + fromChunkdX, intoChunkZ + fromChunkdZ); Dictionary <Vec3i, DepositVariant> SubDepositsToPlace = GenDeposit(chunks, intoChunkX, intoChunkZ, offsetX, offsetZ, variant); foreach (var val in SubDepositsToPlace) { depositRand.SetWorldSeed(chunkRand.NextInt(10000000)); depositRand.InitPositionSeed(intoChunkX + fromChunkdX, intoChunkZ + fromChunkdZ); GenDeposit(chunks, intoChunkX, intoChunkZ, val.Key.X, val.Key.Z, val.Value, val.Key.Y); } } } }
public DepositGeneratorBase(ICoreServerAPI api, DepositVariant variant, LCGRandom depositRand, NormalizedSimplexNoise noiseGen) { this.variant = variant; this.Api = api; this.DepositRand = depositRand; this.DistortNoiseGen = noiseGen; rand = new Random(api.World.Seed); }
protected DiscDepositGenerator(ICoreServerAPI api, DepositVariant variant, LCGRandom depositRand, NormalizedSimplexNoise noiseGen) : base(api, variant, depositRand, noiseGen) { chunksize = api.World.BlockAccessor.ChunkSize; worldheight = api.World.BlockAccessor.MapSizeY; regionSize = api.WorldManager.RegionSize; regionChunkSize = api.WorldManager.RegionSize / chunksize; noiseSizeClimate = regionSize / TerraGenConfig.climateMapScale; noiseSizeOre = regionSize / TerraGenConfig.oreMapScale; }
public override void GeneratePartial(IServerChunk[] chunks, int chunkX, int chunkZ, int chunkdX, int chunkdZ) { int fromChunkx = chunkX + chunkdX; int fromChunkz = chunkZ + chunkdZ; int fromBaseX = fromChunkx * chunksize; int fromBaseZ = fromChunkz * chunksize; subDepositsToPlace.Clear(); float qfac = 1f;// chunks.Length / 8f; for (int i = 0; i < Deposits.Length; i++) { DepositVariant variant = Deposits[i]; /*if (variant.Code != "sphalerite" || chunkdX != 0 || chunkdZ != 0) * { * continue; * }*/ float quantityFactor = variant.WithOreMap ? variant.GetOreMapFactor(fromChunkx, fromChunkz) : 1; float qModified = qfac * variant.TriesPerChunk * quantityFactor * chanceMultiplier; int quantity = (int)qModified; quantity += chunkRand.NextInt(100) < 100 * (qModified - quantity) ? 1 : 0; while (quantity-- > 0) { tmpPos.Set(fromBaseX + chunkRand.NextInt(chunksize), -99, fromBaseZ + chunkRand.NextInt(chunksize)); long crseed = chunkRand.NextInt(10000000); depositRand.SetWorldSeed(crseed); depositRand.InitPositionSeed(fromChunkx, fromChunkz); GenDeposit(chunks, chunkX, chunkZ, tmpPos, variant); } } foreach (var val in subDepositsToPlace) { depositRand.SetWorldSeed(chunkRand.NextInt(10000000)); depositRand.InitPositionSeed(fromChunkx, fromChunkz); val.Value.GeneratorInst.GenDeposit(blockAccessor, chunks, chunkX, chunkZ, val.Key, ref subDepositsToPlace); } }
internal override void OnGameWorldLoaded() { base.OnGameWorldLoaded(); regionSize = api.WorldManager.RegionSize; regionChunkSize = api.WorldManager.RegionSize / chunksize; noiseSizeClimate = regionSize / TerraGenConfig.climateMapScale; noiseSizeOre = regionSize / TerraGenConfig.oreMapScale; int seed = api.WorldManager.Seed; for (int i = 0; i < deposits.variants.Length; i++) { DepositVariant variant = deposits.variants[i]; variant.Init(api); if (variant.WithOreMap) { NoiseOre noiseOre = new NoiseOre(seed++); variant.OreMap = GenMaps.GetOreMap(seed++, noiseOre); } if (variant.ChildDeposits != null) { for (int k = 0; k < variant.ChildDeposits.Length; k++) { DepositVariant childVariant = variant.ChildDeposits[k]; if (childVariant.WithOreMap) { NoiseOre noiseOre = new NoiseOre(seed++); childVariant.OreMap = GenMaps.GetOreMap(seed++, noiseOre); } } } } depositRand = new FastPositionalRandom(api.WorldManager.Seed + 34613); blockTypes = api.World.Blocks; }
public ChildDepositGenerator(ICoreServerAPI api, DepositVariant variant, LCGRandom depositRand, NormalizedSimplexNoise noiseGen) : base(api, variant, depositRand, noiseGen) { }
public virtual void GenDeposit(IServerChunk[] chunks, int chunkX, int chunkZ, BlockPos depoCenterPos, DepositVariant variant) { int lx = GameMath.Mod(depoCenterPos.X, chunksize); int lz = GameMath.Mod(depoCenterPos.Z, chunksize); // Check if suited for this area, climate wise if (variant.Climate != null) { IMapChunk originMapchunk = api.WorldManager.GetMapChunk(depoCenterPos.X / chunksize, depoCenterPos.Z / chunksize); if (originMapchunk == null) { return; // Definition: Climate dependent deposits are limited to size 32x32x32 } depoCenterPos.Y = originMapchunk.RainHeightMap[lz * chunksize + lx]; IntDataMap2D climateMap = blockAccessor.GetMapRegion(depoCenterPos.X / regionSize, depoCenterPos.Z / regionSize).ClimateMap; float posXInRegionClimate = ((float)lx / regionSize - (float)lx / regionSize) * noiseSizeClimate; float posZInRegionClimate = ((float)lz / regionSize - (float)lz / regionSize) * noiseSizeClimate; int climate = climateMap.GetUnpaddedColorLerped(posXInRegionClimate, posZInRegionClimate); float temp = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, depoCenterPos.Y - TerraGenConfig.seaLevel); float rainRel = TerraGenConfig.GetRainFall((climate >> 8) & 0xff, depoCenterPos.Y) / 255f; if (rainRel < variant.Climate.MinRain || rainRel > variant.Climate.MaxRain || temp < variant.Climate.MinTemp || temp > variant.Climate.MaxTemp) { return; } } variant.GeneratorInst?.GenDeposit(blockAccessor, chunks, chunkX, chunkZ, depoCenterPos, ref subDepositsToPlace); }
public void initWorldGen(bool blockCallbacks) { base.initWorldGen(); chanceMultiplier = api.Assets.Get("worldgen/deposits.json").ToObject <Deposits>().ChanceMultiplier; Dictionary <AssetLocation, DepositVariant[]> depositFiles = api.Assets.GetMany <DepositVariant[]>(api.World.Logger, "worldgen/deposits/"); List <DepositVariant> variants = new List <DepositVariant>(); foreach (var val in depositFiles) { foreach (var depo in val.Value) { depo.fromFile = val.Key.ToString(); depo.WithBlockCallback &= blockCallbacks; variants.Add(depo); if (depo.ChildDeposits != null) { foreach (var childdepo in depo.ChildDeposits) { childdepo.fromFile = val.Key.ToString(); childdepo.parentDeposit = depo; childdepo.WithBlockCallback &= blockCallbacks; } } } } Deposits = variants.ToArray(); depositShapeDistortNoise = NormalizedSimplexNoise.FromDefaultOctaves(3, 1 / 10f, 0.9f, 1); regionSize = api.WorldManager.RegionSize; noiseSizeClimate = regionSize / TerraGenConfig.climateMapScale; int seed = api.WorldManager.Seed; depositRand = new LCGRandom(api.WorldManager.Seed + 34613); Dictionary <string, MapLayerBase> maplayersByCode = new Dictionary <string, MapLayerBase>(); for (int i = 0; i < Deposits.Length; i++) { DepositVariant variant = Deposits[i]; variant.Init(api, depositRand, depositShapeDistortNoise); if (variant.WithOreMap) { variant.OreMapLayer = getOrCreateMapLayer(seed, variant.Code, maplayersByCode, variant.OreMapScale, variant.OreMapContrast, variant.OreMapSub); } if (variant.ChildDeposits != null) { for (int k = 0; k < variant.ChildDeposits.Length; k++) { DepositVariant childVariant = variant.ChildDeposits[k]; if (childVariant.WithOreMap) { childVariant.OreMapLayer = getOrCreateMapLayer(seed, childVariant.Code, maplayersByCode, variant.OreMapScale, variant.OreMapContrast, variant.OreMapSub); } } } } verticalDistortBottom = GenMaps.GetDepositVerticalDistort(seed + 12); verticalDistortTop = GenMaps.GetDepositVerticalDistort(seed + 28); }
public AlluvialDepositGenerator(ICoreServerAPI api, DepositVariant variant, LCGRandom depositRand, NormalizedSimplexNoise noiseGen) : base(api, variant, depositRand, noiseGen) { chunksize = api.World.BlockAccessor.ChunkSize; worldheight = api.World.BlockAccessor.MapSizeY; }
private bool ShouldPlaceAdjustedForOreMap(DepositVariant variant, int posX, int posZ, float quantity, float rndVal) { return(!variant.WithOreMap || (variant.GetOreMapFactor(posX / chunksize, posZ / chunksize) * quantity > rndVal)); }
public virtual DepositVariant[] Resolve(DepositVariant sourceVariant) { return(new DepositVariant[] { sourceVariant }); }
public FollowSealevelDiscGenerator(ICoreServerAPI api, DepositVariant variant, LCGRandom depositRand, NormalizedSimplexNoise noiseGen) : base(api, variant, depositRand, noiseGen) { }
/// <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); }