public static void PlaceStructure(Structure structure, Vector3I position, bool eraseSolid = false) { Vector3I shift = structure.Root; Vector3I origin = position - shift; Vector3I extents = structure.Size; ConcurrentDictionary <Vector2I, Chunk> chunkCache = new ConcurrentDictionary <Vector2I, Chunk>(); ushort[] blocks = structure.Blocks; ushort airID = ItemCache.GetIndex("winecrash:air"); Parallel.For(0, blocks.Length, i => { WMath.FlatTo3D(i, extents.X, extents.Y, out int localX, out int localY, out int localZ); Vector3I globalBpos = new Vector3I(localX, localY, localZ) + origin; GlobalToLocal(globalBpos, out Vector2I cpos, out Vector3I bpos); Chunk c; if (!chunkCache.TryGetValue(cpos, out c)) { c = GetChunk(cpos, "winecrash:overworld"); chunkCache.TryAdd(cpos, c); } if (c && (eraseSolid || c.GetBlockIndex(bpos.X, bpos.Y, bpos.Z) == airID)) { c.SetBlock(bpos.X, bpos.Y, bpos.Z, blocks[i]); } });
private static ushort[] GenerateLandmass(Vector2I chunkCoords) { float globalScale = 1.0F; float baseLandmassScale = 0.005F; // lower => wider. yeah ik. float detailBias = 0.0F; float oceanLevel = 63; float landDeformity = 40; float oceanDeformity = 20; float landMaxHeight = oceanLevel + landDeformity; float oceanMaxDepth = oceanLevel - oceanDeformity; float mountainsDeformity = 10; float moutainsScale = 0.01F; float maxLevel = 63 + 40; // this is meant to be used as a 2D base for continents apparently unused \/ IModule3D baseLandmass = new ImprovedPerlin(World.Seed.Value, NoiseQuality.Best); var billow = new Billow { Primitive3D = baseLandmass, OctaveCount = 5.0F, Frequency = 0.9F, }; IModule3D detailsLandmass = new ImprovedPerlin(World.Seed.Value * 123456, NoiseQuality.Best); detailsLandmass = new ScaleBias(detailsLandmass, .2F, detailBias); baseLandmass = new Add(billow, detailsLandmass); //LibNoise.Modifier.Exponent baseLandExp = new Exponent(baseLandmass, 1.0F); //var combiner = new LibNoise.Combiner.Add(baseLandmass1, baseLandmass1); float oceanCoverage = 0.5F; ushort airID = ItemCache.GetIndex("winecrash:air"); ushort stoneID = ItemCache.GetIndex("winecrash:stone"); ushort[] indices = new ushort[Chunk.Width * Chunk.Height * Chunk.Depth]; Vector3F shift = Vector3F.Zero; Vector3F basePos = new Vector3F((chunkCoords.X * Chunk.Width) + shift.X, shift.Y, (chunkCoords.Y * Chunk.Depth) + shift.Z); for (int i = 0; i < Chunk.Width * Chunk.Height * Chunk.Depth; i++) { //Parallel.For(0, Chunk.Width * Chunk.Height * Chunk.Depth, i => //{ indices[i] = airID; // get, from index, the x,y,z coordinates of the block. Then move it from the basePos x scale. WMath.FlatTo3D(i, Chunk.Width, Chunk.Height, out int x, out int y, out int z); if (y > maxLevel) { continue; } Vector3F finalPos = new Vector3F((basePos.X + x) * baseLandmassScale, basePos.Y + y, (basePos.Z + z) * baseLandmassScale) * globalScale; float landMassPct = baseLandmass.GetValue(finalPos.X, 0, finalPos.Z); // retreive the 2D base land value (as seen from top). If under land cap, it's ocean. bool isLand = landMassPct > oceanCoverage; float landPct = (float)Math.Pow(WMath.Remap(landMassPct, oceanCoverage, 1.0F, 0.0F, 1.0F), 2F); float waterPct = WMath.Remap(landMassPct, 0.0F, oceanCoverage, 0.0F, 1.0F); float landMassHeight = oceanLevel + (landPct * landDeformity); int finalLandMassHeight = (int)landMassHeight; float waterHeight = oceanMaxDepth + (waterPct * oceanDeformity); int finalWaterHeight = (int)waterHeight; if (isLand) { if (y < finalLandMassHeight) { indices[i] = stoneID; } } else if (y == oceanLevel - 1) { //indices[i] = waterID; } else if (y < oceanLevel - 1) { if (y > finalWaterHeight) { //indices[i] = waterID; } else { indices[i] = stoneID; } } // debug: display this as grass / sand. //indices[i] = y == 63 ? (isLand ? grassID : sandID) : (y > 63 ? airID : debugID);//debug.GetValue(finalPos.X, finalPos.Y, finalPos.Z) < cap ? stoneID : airID; //}); } return(indices); }