public Cave(ref Random rnd, ref IMapHandler mh, Vector3i StartingPoint) { mMap = mh; rand = rnd; AddPoint(StartingPoint); // We need at least 4 points. int numPoints2Make = rand.Next(3, 10); for(int i=0;i<numPoints2Make;i++) { i++; AddPoint(new Vector3i(StartingPoint.X+rand.Next(-16, 16), StartingPoint.Y+rand.Next(-16, 16), StartingPoint.Z+rand.Next(-16, 16))); } Profiler profSphere = new Profiler("MakeSphere"); Profiler profSpline = new Profiler("GetInterpolatedSplinePoint"); int rad = rand.Next(1, 3); for(int p = 0;p<20;p++) { double t = (double)p/(double)(Points.Count*32); // Between 2/10 radius. profSpline.Start(); Vector3i derp = this.GetInterpolatedSplinePoint(t); profSpline.Stop(); mMap.SetBlockAt(derp.X, derp.Y, derp.Z, 0); profSphere.Start(); MakeSphere(derp, rad); profSphere.Stop(); //Console.WriteLine("MakeSphere r={0} @ t={1}", rad, t); //t += 0.05; } mMap.SaveAll(); Console.WriteLine(profSpline.ToString()); Console.WriteLine(profSphere.ToString()); }
public dlgReplace(IMapHandler mh) { _Map=mh; InitializeComponent(); LockChunkPos(true); LockRect(true); }
/// <summary> /// From the VoxelSim project /// http://github.com/N3X15/VoxelSim /// </summary> /// <param name="X"></param> /// <param name="Z"></param> /// <param name="chunksize"></param> /// <returns></returns> public override double[,] Generate(IMapHandler mh, long X, long Z, out double minHeight, out double maxHeight) { Vector3i chunksize = mh.ChunkScale; int x_o = (int)(X * chunksize.X); int z_o = (int)(Z * chunksize.Z); int YH = (int)chunksize.Y - 2; double[,] hm = new double[chunksize.X, chunksize.Z]; minHeight = (double)chunksize.Y; maxHeight = 0; for (int x = 0; x < chunksize.X; x++) { for (int z = 0; z < chunksize.Z; z++) { double height = 1 - Utils.FixLibnoiseOutput(ContinentNoise.GetValue((double)(x + x_o) / 10d, (double)(z + z_o) / 10d, 0)); height *= 0.5; height += 0.25; height = Utils.Clamp(height, 0.1, 1); if (height < minHeight) { minHeight = height; } if (height > maxHeight) { maxHeight = height; } hm[x, z] = height; } } return(hm); }
/* note, foliage will disintegrate if there is no foliage below, or if there is no "log" block within range 2 (square) at the same level or one level below */ public override void MakeFoliage(ref IMapHandler map) { Console.WriteLine("Adding tree at {0}", Pos); int topy = (int)Pos.Y + Height - 1; int start = topy - 2; int end = topy + 2; for(int y = start;y<end;y++) { int rad=0; if(y > start + 1) rad = 1; else rad = 2; for(int xoff = -rad;xoff<rad+1;xoff++) { for(int zoff = -rad;zoff<rad+1;zoff++) { if (Math.Abs(xoff) == Math.Abs(zoff) && Math.Abs(xoff) == rad) continue; int x = (int)Pos.X + xoff; int z = (int)Pos.Z + zoff; map.SetBlockAt(x,y,z,18); } } } }
public override void MakeFoliage(ref IMapHandler map) { List <Vector3i> foliage_coords = foliage_cords; foreach (Vector3i coord in foliage_coords) { foliagecluster(ref map, coord); } foreach (Vector3i cord in foliage_coords) { map.SetBlockAt(cord.X, cord.Y, cord.Z, 17); if (LIGHTTREE == 1) { map.SetBlockAt(cord.X, cord.Y + 1, cord.Z, 50); map.SetBlockAt(cord.X, cord.Y + 2, cord.Z, 17); } else if (LIGHTTREE == 2 || LIGHTTREE == 4) { map.SetBlockAt(cord.X + 1, cord.Y, cord.Z, 50); map.SetBlockAt(cord.X - 1, cord.Y, cord.Z, 50); if (LIGHTTREE == 4) { map.SetBlockAt(cord.X, cord.Y, cord.Z + 1, 50); map.SetBlockAt(cord.X, cord.Y, cord.Z - 1, 50); } } } }
public static void FixPlayerPlacement(ref IMapHandler mh) { // Thank you #mcp. //<_303> [PlayerPos is] on the head //<_303> corner pointing toward 0,0,0 Vector3d pos = mh.PlayerPos; //<_303> height of player = [1.8] int headblock = mh.GetBlockAt((int)pos.X, (int)pos.Y, (int)pos.Z); switch (headblock) { case 0: case 8: case 9: case 10: case 11: return; } for (int y = (int)mh.ChunkScale.Y - 3; y > 1; y--) { int supportblock = mh.GetBlockAt((int)pos.X, y - 3, (int)pos.Z); if (supportblock != 0) { mh.PlayerPos.Y = y; return; } } }
/// <summary> /// Create a round section of type matidx in blocklist. /// </summary> /// <param name="map"></param> /// <param name="vCenter">the coordinates of the center block</param> /// <param name="radius">the radius of the section.</param> /// <param name="diraxis">The list index for the axis to make the section perpendicular to. 0 indicates the x axis, 1 the y, 2 the z. The section will extend along the other two axies.</param> /// <param name="mat">What to make the section out of</param> public void crossection(ref IMapHandler map, Vector3i vCenter, double radius, int diraxis, byte mat) { long[] centArray = vCenter.ToArray(); int rad = (int)(radius + .618d); int secidx1 = (diraxis - 1) % 3; int secidx2 = (1 + diraxis) % 3; int[] coord = new int [] { 0, 0, 0 }; for (int off1 = -rad; off1 < rad + 1; off1++) { for (int off2 = -rad; off2 < rad + 1; off2++) { double thisdist = Math.Sqrt(Math.Pow((double)Math.Abs(off1) + .5d, 2d) + Math.Pow((double)Math.Abs(off2) + .5d, 2)); if (thisdist > radius) { continue; } int pri = (int)centArray[diraxis]; int sec1 = (int)centArray[secidx1] + off1; int sec2 = (int)centArray[secidx2] + off2; coord[diraxis] = pri; coord[secidx1] = sec1; coord[secidx2] = sec2; map.SetBlockAt(coord[0], coord[1], coord[2], mat); } } }
/// <summary> /// Generate a chunk /// </summary> /// <param name="CX">Chunk X</param> /// <param name="CZ">Chunk Z</param> /// <param name="b">Blocks</param> /// <param name="mh">Map handler</param> /// <param name="r">Random</param> /// <returns></returns> public static bool MakeDungeon(int CX, int CZ, ref byte[, ,] b, ref IMapHandler mh, Random r) { int CH = (int)mh.ChunkScale.X; int CV = (int)mh.ChunkScale.Y; int x = r.Next(0 + DungeonSizeX - 1, CH - DungeonSizeX + 1); int y = r.Next(0 + DungeonSizeY - 1, CV - DungeonSizeY + 1); int z = r.Next(0 + DungeonSizeZ - 1, CH - DungeonSizeZ + 1); Vector3i position = mh.Local2Global(CX, CZ, new Vector3i(x, y, z)); //Console.WriteLine("Creating dungeon in {0}...", position); if (!CheckForDungeonSpace(b, x, y, z)) { return(false); } Vector3i size = new Vector3i((DungeonSizeX * 2) + 1, (DungeonSizeY * 2) + 1, (DungeonSizeZ * 2) + 1); Vector3i sizeAir = new Vector3i(size.X - 1, size.Y - 1, size.Z - 1); FillRect(ref b, 48, position, size); // Do walls (RANDOMIZE) FillRect(ref b, 0, position, sizeAir); // Add air MobSpawner ms = new MobSpawner(); ms.Delay = 20; ms.EntityId = Entity.GetRandomMonsterID(r); ms.Pos = mh.Local2Global(CX, CZ, new Vector3i(x, y - DungeonSizeZ + 1, z)); ms.UUID = Guid.NewGuid(); mh.SetTileEntity(ms); b[x, y - DungeonSizeZ + 1, z] = 52; return(true); }
/* * note, foliage will disintegrate if there is no foliage below, or * if there is no "log" block within range 2 (square) at the same level or * one level below */ public override void MakeFoliage(ref IMapHandler map) { Console.WriteLine("Adding tree at {0}", Pos); int topy = (int)Pos.Y + Height - 1; int start = topy - 2; int end = topy + 2; for (int y = start; y < end; y++) { int rad = 0; if (y > start + 1) { rad = 1; } else { rad = 2; } for (int xoff = -rad; xoff < rad + 1; xoff++) { for (int zoff = -rad; zoff < rad + 1; zoff++) { if (Math.Abs(xoff) == Math.Abs(zoff) && Math.Abs(xoff) == rad) { continue; } int x = (int)Pos.X + xoff; int z = (int)Pos.Z + zoff; map.SetBlockAt(x, y, z, 18); } } } }
public Chunk(IMapHandler mh) { Map = mh; Overview = new byte[mh.ChunkScale.X, mh.ChunkScale.Z]; HeightMap = new int[mh.ChunkScale.X, mh.ChunkScale.Z]; WaterDepth = new int[mh.ChunkScale.X, mh.ChunkScale.Z]; }
public dlgTerrainGen(IMapHandler _mh) { mh = _mh; InitializeComponent(); cmbMapGenSel.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; cmbMapGenSel.DrawItem += new DrawItemEventHandler(cmbMapGenSel_DrawItem); LockCheckboxes(true); }
/// <summary> /// Generate branches. /// </summary> /// <param name="map"></param> public void makebranches(ref IMapHandler map) { long topy = Pos[1] + (int)((int)trunkheight + 0.5d); double endrad = trunkradius * (1 - trunkheight / Height); if (endrad < 1.0) { endrad = 1.0; } foreach (Vector3i coord in foliage_cords) { double dist = Math.Sqrt( Math.Pow(coord.X - Pos.X, 2d) + Math.Pow(coord.Z - Pos.Z, 2d)); double ydist = coord.Y - Pos.Y; double value = (branchdensity * 220 * Height) / Math.Pow((ydist + dist), 3d); if (value < rand.NextDouble()) { continue; } long posy = coord.Y; double slope = branchslope + (0.5 - rand.NextDouble()) * .16; long branchy; double basesize; if (coord.Y - dist * slope > topy) { double threshhold = 1d / (double)(Height); if (rand.NextDouble() < threshhold) { continue; } branchy = topy; basesize = endrad; } else { branchy = (long)(posy - dist * slope); basesize = (endrad + (trunkradius - endrad) * (topy - branchy) / trunkheight); } double startsize = (basesize * (1 + rand.NextDouble()) * .618 * Math.Pow(dist / Height, 0.618)); double rndr = Math.Sqrt(rand.NextDouble()) * basesize * 0.618; double rndang = rand.NextDouble() * 2 * Math.PI; int rndx = (int)(rndr * Math.Sin(rndang) + 0.5); int rndz = (int)(rndr * Math.Cos(rndang) + 0.5); Vector3i startcoord = new Vector3i(Pos[0] + rndx, (int)branchy, Pos[2] + rndz); if (startsize < 1.0) { startsize = 1.0; } double endsize = 1.0; taperedlimb(ref map, startcoord, coord, (int)startsize, (int)endsize); } }
public override void DoBlockLighting(IMapHandler _mh, long X, long Y) { int csx = (int)_mh.ChunkScale.X; int csy = (int)_mh.ChunkScale.Y; for (int i = 0; i < 15; i++) { for (int _x = 0; _x < csx; _x++) { for (int _y = 0; _y < csy; _y++) { int x = (int)(X * _mh.ChunkScale.X) + _x; int y = (int)(Y * _mh.ChunkScale.Y) + _y; for (int z = 0; z < _mh.GetHeightAt(x, y); z++) { byte currentBlockLight,currentSkyLight; _mh.GetLightAt(x, y, z, out currentSkyLight, out currentBlockLight); byte currentBlock = _mh.GetBlockAt(x, y, z); Block currentBlockInfo = OpenMinecraft.Blocks.Get(currentBlock); // SUNLIGHT currentSkyLight = (byte)(currentSkyLight - currentBlockInfo.Stop - 1); if (currentBlockInfo.Emit > 0) currentBlockLight = currentBlockInfo.Emit; // Get brightest neighbor if (x < csx - 1 && currentBlockLight < _mh.GetBlockLightAt(x + 1, y, z)) currentBlockLight = _mh.GetBlockLightAt(x + 1, y, z); if (y < csy - 1 && currentBlockLight < _mh.GetBlockLightAt(x, y + 1, z)) currentBlockLight = _mh.GetBlockLightAt(x, y + 1, z); if (z < _mh.ChunkScale.Z - 1 && currentBlockLight < _mh.GetBlockLightAt(x, y, z + 1)) currentBlockLight = _mh.GetBlockLightAt(x, y, z + 1); if (x > 0 && currentBlockLight < _mh.GetBlockLightAt(x - 1, y, z)) currentBlockLight = _mh.GetBlockLightAt(x - 1, y, z); if (y > 0 && currentBlockLight < _mh.GetBlockLightAt(x, y - 1, z)) currentBlockLight = _mh.GetBlockLightAt(x, y - 1, z); if (z > 0 && currentBlockLight < _mh.GetBlockLightAt(x, y, z - 1)) currentBlockLight = _mh.GetBlockLightAt(x, y, z - 1); // Drop 1 level of light + lightstop for current block currentBlockLight = (byte)(currentBlockLight - 1 - currentBlockInfo.Stop); if (currentBlockLight < 0) currentBlockLight = 0; if (currentBlockLight > 15) currentBlockLight = 15; if (currentSkyLight < 0) currentSkyLight = 0; if (currentSkyLight > 15) currentSkyLight = 15; _mh.SetBlockLightAt(x, y, z, currentBlockLight); _mh.SetSkyLightAt(x, y, z, currentSkyLight); } } } } }
/// <summary> /// generate a round cluster of foliage at the location center. /// /// The shape of the cluster is defined by the list foliage_shape. /// This list must be set in a subclass of ProceduralTree. /// </summary> /// <param name="map"></param> /// <param name="center"></param> public void foliagecluster(ref IMapHandler map, Vector3i center) { List <int> level_radius = this.foliage_shape; foreach (int i in level_radius) { crossection(ref map, center, (double)i, 1, 18); center.Y++; } }
public override void DoSkyLighting(IMapHandler _mh, long X, long Y) { Chunk c = _mh.GetChunk(X, Y); if (c == null) { return; } this.DoSkylighting(c); }
public virtual void ResetLightingData(ref IMapHandler mh) { mh.ForEachChunk(delegate(IMapHandler _mh, long X, long Y) { Chunk c = _mh.GetChunk(X, Y); c.UpdateOverview(); c.SkyLight = new byte[c.Size.X, c.Size.Y, c.Size.Z]; c.BlockLight = new byte[c.Size.X, c.Size.Y, c.Size.Z]; _mh.SetChunk(X, Y, c); }); }
/// <summary> /// Initialize and set up events for this MapChunk. /// </summary> /// <param name="mc">Parent mapcontrol</param> /// <param name="pos">Position of chunk</param> /// <param name="sz">Chunk size</param> public MapChunkControl(MapControl mc,Vector3i pos,Vector3i sz) { parent=mc; Map = parent.Map; AssignedChunk = pos; ChunkSize = sz; MyChunk = Map.GetChunk(AssignedChunk); //Console.WriteLine("{0}: Chunk ({1},{2}), origin ({3},{4}), size {5}", this, pos.X, pos.Y, pos.X * sz.X, pos.Y * sz.Y, sz); InitializeComponent(); Paint += new PaintEventHandler(MapChunkControl_Paint); }
// CHUNKS(PK(cnkX, cnkZ), cnkTemperatureMap, cnkHumidityMap, cnkOriginalVoxels) // TREES(PK(treeX,treeZ), treeHeight, treeType) // DUNGEONS(PK(dgnPos), dgnSpawns) public MapMetadata(IMapHandler _map, string folder) { map=_map; Filename=Path.Combine(folder, "mineedit.cache"); FirstCache = !File.Exists(Filename); string dsn = string.Format(@"Data Source={0};Version=3", Filename); database = new SQLiteConnection(dsn); database.Open(); //database.ChangeDatabase("MineEdit"); BuildDatabaseIfNeeded(); }
public override void MakeTrunk(ref IMapHandler map) { int x = (int)Pos.X; int y = (int)Pos.Y; int z = (int)Pos.Z; for (int i = 0; i < Height; i++) { map.SetBlockAt(x, y, z, 17); y += 1; } }
public override void MakeTrunk(ref IMapHandler map) { int x = (int)Pos.X; int y = (int)Pos.Y; int z = (int)Pos.Z; for (int i = 0; i<Height;i++) { map.SetBlockAt(x, y, z, 17); y += 1; } }
private bool GetFileHandler(string FileName, out IMapHandler mh) { mh = null; foreach (IMapHandler _mh in FileHandlers) { if (_mh.IsMyFiletype(FileName)) { mh = _mh; return true; } } return false; }
// CHUNKS(PK(cnkX, cnkZ), cnkTemperatureMap, cnkHumidityMap, cnkOriginalVoxels) // TREES(PK(treeX,treeZ), treeHeight, treeType) // DUNGEONS(PK(dgnPos), dgnSpawns) public MapMetadata(IMapHandler _map, string folder) { map = _map; Filename = Path.Combine(folder, "mineedit.cache"); FirstCache = !File.Exists(Filename); string dsn = string.Format(@"Data Source={0};Version=3", Filename); database = new SQLiteConnection(dsn); database.Open(); //database.ChangeDatabase("MineEdit"); BuildDatabaseIfNeeded(); }
public dlgChunk(IMapHandler m,Vector3i pos) { InitializeComponent(); if (m == null) { MessageBox.Show("m==null"); Environment.Exit(-1); } Map = m; //mcc.Map = m; //mcc.Render(); //mcc.Refresh(); ChunkPos = pos; }
public virtual void AddDungeons(ref byte[, ,] b, ref IMapHandler mh, Random rand, long X, long Z) { if (!this.GenerateDungeons) { return; } if (rand.Next(0, 100) == 0) { int DungeonTries = 128; while (!Utils.MakeDungeon((int)X, (int)Z, ref b, ref mh, rand)) { //Console.WriteLine("Making dungeon..."); if (DungeonTries-- == 0) { break; } } } }
/// <summary> /// Smooths below-water surfaces and, optionally, adds beaches. /// </summary> /// <param name="waterlevel"> /// A <see cref="System.Single"/> /// </param> /// <param name="beaches"> /// A <see cref="System.Boolean"/> /// </param> /// <returns> /// A <see cref="Channel"/> /// </returns> public void Silt(double waterlevel, bool beaches, int X, int Z) { // 1. Copy Image // 2. Apply gauss blur to lower layer // 3. Bring back unblurred terrain from above the water level. int x_o = X * (int)ChunkScale.X; int z_o = Z * (int)ChunkScale.Z; double wl = (beaches) ? waterlevel + 6d : waterlevel; wl = wl / 256f; // Gaussian blur for silt and beaches. double[][] gaussian_matrix = new double[3][] { new double[3] { 1, 2, 1 }, new double[3] { 2, 4, 2 }, new double[3] { 1, 2, 1 } }; IMapHandler Blurred = this; Blurred.Convolution(gaussian_matrix, 32f, waterlevel / 2d, X, Z); for (int x = 0; x < ChunkScale.X; x++) { for (int z = 0; z < ChunkScale.Z; z++) { // If > WL: use unblurred image. // If <=WL: Use blurred image. if (GetPrelimHeightAt(x + x_o, z + z_o) <= wl) { SetPrelimHeightAt(x + x_o, z + z_o, Blurred.GetPrelimHeightAt(x + x_o, z + z_o)); } } } }
public Cave(ref Random rnd, ref IMapHandler mh, Vector3i StartingPoint) { mMap = mh; rand = rnd; AddPoint(StartingPoint); // We need at least 4 points. int numPoints2Make = rand.Next(3, 10); for (int i = 0; i < numPoints2Make; i++) { i++; AddPoint(new Vector3i(StartingPoint.X + rand.Next(-16, 16), StartingPoint.Y + rand.Next(-16, 16), StartingPoint.Z + rand.Next(-16, 16))); } Profiler profSphere = new Profiler("MakeSphere"); Profiler profSpline = new Profiler("GetInterpolatedSplinePoint"); int rad = rand.Next(1, 3); for (int p = 0; p < 20; p++) { double t = (double)p / (double)(Points.Count * 32); // Between 2/10 radius. profSpline.Start(); Vector3i derp = this.GetInterpolatedSplinePoint(t); profSpline.Stop(); mMap.SetBlockAt(derp.X, derp.Y, derp.Z, 0); profSphere.Start(); MakeSphere(derp, rad); profSphere.Stop(); //Console.WriteLine("MakeSphere r={0} @ t={1}", rad, t); //t += 0.05; } mMap.SaveAll(); Console.WriteLine(profSpline.ToString()); Console.WriteLine(profSphere.ToString()); }
/// <summary> /// Generate branches. /// </summary> /// <param name="map"></param> public void makebranches(ref IMapHandler map) { long topy = Pos[1]+(int)((int)trunkheight + 0.5d); double endrad = trunkradius * (1 - trunkheight/Height); if(endrad < 1.0) endrad = 1.0; foreach(Vector3i coord in foliage_cords) { double dist = Math.Sqrt( Math.Pow(coord.X - Pos.X,2d) + Math.Pow(coord.Z - Pos.Z,2d)); double ydist = coord.Y-Pos.Y; double value = (branchdensity * 220 * Height)/Math.Pow((ydist + dist), 3d); if(value < rand.NextDouble()) continue; long posy = coord.Y; double slope = branchslope + (0.5 - rand.NextDouble())*.16; long branchy; double basesize; if(coord.Y - dist*slope > topy) { double threshhold = 1d / (double)(Height); if(rand.NextDouble() < threshhold) continue; branchy = topy; basesize = endrad; } else { branchy = (long)(posy-dist*slope); basesize = (endrad + (trunkradius-endrad) * (topy - branchy) / trunkheight); } double startsize = (basesize * (1 + rand.NextDouble()) * .618 * Math.Pow(dist/Height,0.618)); double rndr = Math.Sqrt(rand.NextDouble())*basesize*0.618; double rndang = rand.NextDouble()*2*Math.PI; int rndx = (int)(rndr*Math.Sin(rndang) + 0.5); int rndz = (int)(rndr*Math.Cos(rndang) + 0.5); Vector3i startcoord = new Vector3i(Pos[0]+rndx, (int)branchy, Pos[2]+rndz); if(startsize < 1.0) startsize = 1.0; double endsize = 1.0; taperedlimb(ref map, startcoord, coord, (int)startsize, (int)endsize); } }
public override void MakeTrunk(ref IMapHandler map) { int starty = (int)Pos[1]; int midy = (int)(Pos[1] + (trunkheight * .382)); int topy = (int)(Pos[1] + (trunkheight + 0.5)); // In this method, x and z are the position of the trunk. long x = Pos[0]; long z = Pos[2]; double midrad = trunkradius * .8; double endrad = trunkradius * (1 - trunkheight / Height); if (endrad < 1.0) { endrad = 1.0; } if (midrad < endrad) { midrad = endrad; } List <Vector3i> rootbases = new List <Vector3i>(); // Make the root buttresses, if indicated double startrad; if (ROOTBUTTRESSES || SHAPE == "mangrove") { // The start radius of the trunk should be a little smaller if we // are using root buttresses. startrad = trunkradius * .8; // rootbases is used later in makeroots(...) as // starting locations for the roots. rootbases.Add(new Vector3i(x, z, (long)startrad)); double buttress_radius = trunkradius * 0.382; // posradius is how far the root buttresses should be offset // from the trunk. double posradius = trunkradius; // In mangroves, the root buttresses are much more extended. if (SHAPE == "mangrove") { posradius = posradius * 2.618; } int num_of_buttresses = (int)(Math.Sqrt(trunkradius) + 3.5); for (int i = 0; i < num_of_buttresses; i++) { double rndang = rand.NextDouble() * 2 * Math.PI; double thisposradius = posradius * (0.9 + rand.NextDouble() * .2); // thisx and thisz are the x and z position for the base of // the root buttress. long thisx = x + (long)(thisposradius * Math.Sin(rndang)); long thisz = z + (long)(thisposradius * Math.Cos(rndang)); // thisbuttressradius is the radius of the buttress. // Currently, root buttresses do not taper. double thisbuttressradius = buttress_radius * (0.618 + rand.NextDouble()); if (thisbuttressradius < 1.0) { thisbuttressradius = 1.0; } // Make the root buttress. taperedlimb(ref map, new Vector3i(thisx, starty, thisz), new Vector3i(x, midy, z), (int)thisbuttressradius, (int)thisbuttressradius); // Add this root buttress as a possible location at // which roots can spawn. rootbases.Add(new Vector3i(thisx, thisz, (long)thisbuttressradius)); } } else { // If root buttresses are turned off, set the trunk radius // to normal size. rootbases.Clear(); startrad = trunkradius; rootbases.Add(new Vector3i(x, z, (long)trunkradius)); } // Make the lower and upper sections of the trunk. taperedlimb(ref map, new Vector3i(x, starty, z), new Vector3i(x, midy, z), (int)startrad, (int)midrad); taperedlimb(ref map, new Vector3i(x, midy, z), new Vector3i(x, topy, z), (int)midrad, (int)endrad); // Make the branches makebranches(ref map); // Make the roots, if indicated. if (ROOTS == "yes" || ROOTS == "tostone" || ROOTS == "hanging") { makeroots(ref map, rootbases); } }
//Generate the trunk and enter it in blocklist. public virtual void MakeTrunk(ref IMapHandler map) { }
public virtual void SkylightGlobal(ref IMapHandler mh) { mh.ForEachChunk(DoSkyLighting); }
public virtual void AddTrees(ref IMapHandler mh, BiomeType[,] biomes, ref Random rand, int X, int Z, int H) { int xo = (int)(X * mh.ChunkScale.X); int zo = (int)(Z * mh.ChunkScale.Z); List <Vector2i> PlantedTrees = new List <Vector2i>(); int DistanceReqd = 3; for (int t = 0; t < (int)((HumidityNoise.Noise((double)(xo) / BIOME_SCALE, (double)(zo) / BIOME_SCALE, 0) + HumidityOffset) * 5.0); t++) { Vector2i me = new Vector2i(rand.Next(0, 15), rand.Next(0, 15)); if (!Biome.NeedsTrees(biomes[me.X, me.Y])) { continue; } bool tooclose = false; foreach (Vector2i tree in PlantedTrees) { if (Vector2i.Distance(tree, me) < DistanceReqd) { tooclose = true; break; } } if (tooclose) { continue; } bool founddert = false; for (int y = (int)H - 10; y > 0; y--) { switch (mh.GetBlockAt(me.X + xo, y, me.Y + zo)) { case 0: // Air case 78: // Snow cover continue; // case 1: // ROCK case 2: // GRASS case 3: // DIRT //Utils.GrowTree(ref blocks, rand, (int)me.X, (int)y + 1, (int)me.Y); mh.SetBlockAt(me.X + xo, y + 1, me.Y + zo, 6); // Sapling mh.SetDataAt(me.X + xo, y + 1, me.Y + zo, 15); // Growth stage 15. /* * Tree tree = new NormalTree(me.X + xo, y + 1, me.Y + zo, rand.Next(5, 8)); * tree.MakeTrunk(ref mh); * tree.MakeFoliage(ref mh); */ mh.SaveAll(); founddert = true; break; case 11: // SAND //Utils.GrowCactus(ref b, rand, me.X, y + 1, me.Y); break; default: founddert = true; break; } if (founddert) { break; } } PlantedTrees.Add(me); } }
/// <summary> /// Create a tapered cylinder in blocklist. /// start and end are the beginning and ending coordinates of form [x,y,z]. /// startsize and endsize are the beginning and ending radius. /// The material of the cylinder is 17, which indicates wood in Minecraft. /// </summary> /// <param name="map"></param> /// <param name="start"></param> /// <param name="end"></param> /// <param name="startsize"></param> /// <param name="endsize"></param> public void taperedlimb(ref IMapHandler map, Vector3i vStart, Vector3i vEnd, int startsize, int endsize) { // delta is the coordinate vector for the difference between // start and end. Vector3i vDelta = vEnd - vStart; long[] delta = vDelta.ToArray(); long[] start = vStart.ToArray(); long[] end = vEnd.ToArray(); // primidx is the index (0,1,or 2 for x,y,z) for the coordinate // which has the largest overall delta. long maxdist = 0; int primidx=0; for(int i = 0;i<3;i++) { if(Math.Abs(delta[i])>maxdist) { maxdist=delta[i]; primidx=i; } } if(maxdist == 0) return; // secidx1 and secidx2 are the remaining indicies out of [0,1,2]. int secidx1 = (primidx - 1)%3; int secidx2 = (1 + primidx)%3; // primsign is the digit 1 or -1 depending on whether the limb is headed // along the positive or negative primidx axis. long primsign = delta[primidx]/Math.Abs(delta[primidx]); // secdelta1 and ...2 are the amount the associated values change // for every step along the prime axis. long secdelta1 = delta[secidx1]; double secfac1 = (double)(secdelta1)/delta[primidx]; long secdelta2 = delta[secidx2]; double secfac2 = (double)(secdelta2)/delta[primidx]; // Initialize coord. These values could be anything, since // they are overwritten. long[] coord = new long[]{0,0,0}; // Loop through each crossection along the primary axis, // from start to end. long endoffset = delta[primidx] + primsign; for(long primoffset=0;primoffset<endoffset;primoffset+=primsign)//primoffset in range(0, endoffset, primsign): { long primloc = start[primidx] + primoffset; int secloc1 = (int)(start[secidx1] + primoffset*secfac1); int secloc2 = (int)(start[secidx2] + primoffset*secfac2); coord[primidx] = primloc; coord[secidx1] = secloc1; coord[secidx2] = secloc2; long primdist = Math.Abs(delta[primidx]); int radius = (int)(endsize + (startsize-endsize) * Math.Abs(delta[primidx] - primoffset) / primdist); crossection(ref map,new Vector3i(coord[0],coord[1],coord[2]),radius,primidx,17); } }
public virtual void BlocklightGlobal(ref IMapHandler mh) { mh.ForEachChunk(DoBlockLighting); }
/// <summary> /// generate a round cluster of foliage at the location center. /// /// The shape of the cluster is defined by the list foliage_shape. /// This list must be set in a subclass of ProceduralTree. /// </summary> /// <param name="map"></param> /// <param name="center"></param> public void foliagecluster(ref IMapHandler map, Vector3i center) { List<int> level_radius = this.foliage_shape; foreach(int i in level_radius) { crossection(ref map, center,(double)i,1,18); center.Y++; } }
/// <param name="X"></param> /// <param name="Y"></param> /// <param name="chunksize"></param> /// <returns></returns> public abstract byte[, ,] Generate(ref IMapHandler mh, long X, long Y);
/// <summary> /// From the VoxelSim project /// http://github.com/N3X15/VoxelSim /// </summary> /// <param name="X"></param> /// <param name="Z"></param> /// <param name="chunksize"></param> /// <returns></returns> public override double[,] Generate(IMapHandler mh, long X, long Z, out double minHeight, out double maxHeight) { Vector3i chunksize = mh.ChunkScale; int x_o = (int)(X * chunksize.X); int z_o = (int)(Z * chunksize.Z); int YH = (int)chunksize.Y-2; double[,] hm = new double[chunksize.X, chunksize.Z]; minHeight = (double)chunksize.Y; maxHeight = 0; for (int x = 0; x < chunksize.X; x++) { for (int z = 0; z < chunksize.Z; z++) { double height = 1-Utils.FixLibnoiseOutput(ContinentNoise.GetValue((double)(x + x_o) / 10d, (double)(z + z_o) / 10d, 0)); height *= 0.5; height += 0.25; height = Utils.Clamp(height, 0.1, 1); if (height < minHeight) minHeight = height; if (height > maxHeight) maxHeight = height; hm[x, z] = height; } } return hm; }
public override void DoBlockLighting(IMapHandler _mh, long X, long Y) { int csx = (int)_mh.ChunkScale.X; int csy = (int)_mh.ChunkScale.Y; for (int i = 0; i < 15; i++) { for (int _x = 0; _x < csx; _x++) { for (int _y = 0; _y < csy; _y++) { int x = (int)(X * _mh.ChunkScale.X) + _x; int y = (int)(Y * _mh.ChunkScale.Y) + _y; for (int z = 0; z < _mh.GetHeightAt(x, y); z++) { byte currentBlockLight, currentSkyLight; _mh.GetLightAt(x, y, z, out currentSkyLight, out currentBlockLight); byte currentBlock = _mh.GetBlockAt(x, y, z); Block currentBlockInfo = OpenMinecraft.Blocks.Get(currentBlock); // SUNLIGHT currentSkyLight = (byte)(currentSkyLight - currentBlockInfo.Stop - 1); if (currentBlockInfo.Emit > 0) { currentBlockLight = currentBlockInfo.Emit; } // Get brightest neighbor if (x < csx - 1 && currentBlockLight < _mh.GetBlockLightAt(x + 1, y, z)) { currentBlockLight = _mh.GetBlockLightAt(x + 1, y, z); } if (y < csy - 1 && currentBlockLight < _mh.GetBlockLightAt(x, y + 1, z)) { currentBlockLight = _mh.GetBlockLightAt(x, y + 1, z); } if (z < _mh.ChunkScale.Z - 1 && currentBlockLight < _mh.GetBlockLightAt(x, y, z + 1)) { currentBlockLight = _mh.GetBlockLightAt(x, y, z + 1); } if (x > 0 && currentBlockLight < _mh.GetBlockLightAt(x - 1, y, z)) { currentBlockLight = _mh.GetBlockLightAt(x - 1, y, z); } if (y > 0 && currentBlockLight < _mh.GetBlockLightAt(x, y - 1, z)) { currentBlockLight = _mh.GetBlockLightAt(x, y - 1, z); } if (z > 0 && currentBlockLight < _mh.GetBlockLightAt(x, y, z - 1)) { currentBlockLight = _mh.GetBlockLightAt(x, y, z - 1); } // Drop 1 level of light + lightstop for current block currentBlockLight = (byte)(currentBlockLight - 1 - currentBlockInfo.Stop); if (currentBlockLight < 0) { currentBlockLight = 0; } if (currentBlockLight > 15) { currentBlockLight = 15; } if (currentSkyLight < 0) { currentSkyLight = 0; } if (currentSkyLight > 15) { currentSkyLight = 15; } _mh.SetBlockLightAt(x, y, z, currentBlockLight); _mh.SetSkyLightAt(x, y, z, currentSkyLight); } } } } }
public void makeroots(ref IMapHandler map, List <Vector3i> rootbases) { foreach (Vector3i coord in foliage_cords) { // First, set the threshhold for randomly selecting this // coordinate for root creation. double dist = Math.Sqrt(Math.Pow(coord[0] - Pos[0], 2) + Math.Pow(coord[2] - Pos[2], 2)); double ydist = coord[1] - Pos[1]; double value = (branchdensity * 220 * Height) / Math.Pow((ydist + dist), 3d); // Randomly skip roots, based on the above threshold if (value < rand.NextDouble()) { continue; } // initialize the internal variables from a selection of // starting locations. int ci = rand.Next(0, rootbases.Count - 1); Vector3i rootbase = rootbases[ci]; long rootx = rootbase[0]; long rootz = rootbase[1]; double rootbaseradius = rootbase[2]; // Offset the root origin location by a random amount // (radialy) from the starting location. double rndr = (Math.Sqrt(rand.NextDouble()) * rootbaseradius * .618); double rndang = rand.NextDouble() * 2 * Math.PI; int rndx = (int)(rndr * Math.Sin(rndang) + 0.5); int rndz = (int)(rndr * Math.Cos(rndang) + 0.5); int rndy = (int)(rand.NextDouble() * rootbaseradius * 0.5); Vector3i startcoord = new Vector3i(rootx + rndx, Pos[1] + rndy, rootz + rndz); // offset is the distance from the root base to the root tip. Vector3i offset = startcoord - coord; // If this is a mangrove tree, make the roots longer. if (SHAPE == "mangrove") { offset = (offset * 1.618) - 1.5; } Vector3i endcoord = startcoord + offset; double rootstartsize = (rootbaseradius * 0.618 * Math.Abs(offset[1]) / (Height * 0.618)); if (rootstartsize < 1.0) { rootstartsize = 1.0; } double endsize = 1.0; // If ROOTS is set to "tostone" or "hanging" we need to check // along the distance for collision with existing materials. if (ROOTS == "tostone" || ROOTS == "hanging") { double offlength = Math.Sqrt( Math.Pow(offset[0], 2) + Math.Pow(offset[1], 2) + Math.Pow(offset[2], 2)); if (offlength < 1) { continue; } double rootmid = endsize; // vec is a unit vector along the direction of the root. Vector3i vec = offset / offlength; byte searchindex; if (ROOTS == "tostone") { searchindex = 1; } else // Hanging { searchindex = 0; } // startdist is how many steps to travel before starting to // search for the material. It is used to ensure that large // roots will go some distance before changing directions // or stopping. double startdist = (int)(rand.NextDouble() * 6 * Math.Sqrt(rootstartsize) + 2.8); // searchstart is the coordinate where the search should begin Vector3i searchstart = (startcoord + startdist) * vec; // dist stores how far the search went (including searchstart) // before encountering the expected marterial. dist = startdist + map.DistanceToMaterial(searchstart, vec, searchindex); // If the distance to the materila is less than the length // of the root, change the end point of the root to where // the search found the material. if (dist < offlength) { // rootmid is the size of the crossection at endcoord. rootmid += (rootstartsize - endsize) * (1 - dist / offlength); } // endcoord is the midpoint for hanging roots, // and the endpoint for roots stopped by stone. endcoord = startcoord + (vec * dist); if (ROOTS == "hanging") { // remaining_dist is how far the root had left // to go when it was stopped. double remaining_dist = offlength - dist; // Initialize bottomcord to the stopping point of // the root, and then hang straight down // a distance of remaining_dist. Vector3i bottomcord = endcoord; bottomcord.Y += -(long)remaining_dist; // Make the hanging part of the hanging root. taperedlimb(ref map, endcoord, bottomcord, (int)rootmid, (int)endsize); } // make the beginning part of hanging or "tostone" roots taperedlimb(ref map, startcoord, endcoord, (int)rootstartsize, (int)rootmid); // If you aren't searching for stone or air, just make the root. } else { taperedlimb(ref map, startcoord, endcoord, (int)rootstartsize, (int)endsize); } } }
public abstract double[,] Generate(IMapHandler map, long X, long Z, out double min, out double max);
public void Generate(IMapHandler mh, long X, long Y) { if (_Generator == null) return; string lockfile = Path.ChangeExtension(GetChunkFilename((int)X,(int)Y), "genlock"); if (!_Generator.NoPreservation) { if (File.Exists(lockfile)) return; } else { if (File.Exists(lockfile)) File.Delete(lockfile); } Chunk _c = mh.NewChunk(X, Y); byte[,,] b = _Generator.Generate(ref mh, X, Y); if (b == null) return; /* try { //Console.WriteLine("{0} blocks of stone post-generation.", GetBlockNumbers(b)[1]); } catch (Exception) { } */ _Generator.AddTrees(ref b, (int)X, (int)Y, (int)ChunkScale.Z); _c.Blocks = b; _c.UpdateOverview(); //_c.SkyLight=Utils.RecalcLighting(_c,true); //_c.BlockLight=Utils.RecalcLighting(_c,false); _c.Save(); File.WriteAllText(lockfile, ""); }
/// <summary> /// Generate the foliage and enter it in blocklist. /// /// Note, foliage will disintegrate if there is no foliage below, or /// if there is no "log" block within range 2 (square) at the same level or /// one level below /// </summary> /// <param name="map"></param> public virtual void MakeFoliage(ref IMapHandler map) { }
public abstract void DoSkyLighting(IMapHandler _mh, long X, long Y);
void mh_StatusUpdate(IMapHandler _mh, short status, string message) { //Console.WriteLine("[STATUSUPDATE] " + message); if (status != 0) { tsbStatus.Text = message.Replace("\r\n"," "); tsbProgress.Style = ProgressBarStyle.Marquee; if (mStatusWindow == null) { mStatusWindow = new dlgStatus(_mh, message); mStatusWindow.Show(); } } else { ResetStatus(); tsbStatus.Text = ""; tsbProgress.Style = ProgressBarStyle.Continuous; } }
public override void MakeFoliage(ref IMapHandler map) { List<Vector3i> foliage_coords = foliage_cords; foreach(Vector3i coord in foliage_coords) { foliagecluster(ref map,coord); } foreach(Vector3i cord in foliage_coords) { map.SetBlockAt(cord.X,cord.Y,cord.Z,17); if(LIGHTTREE == 1) { map.SetBlockAt(cord.X,cord.Y+1,cord.Z,50); map.SetBlockAt(cord.X,cord.Y+2,cord.Z,17); } else if (LIGHTTREE == 2 || LIGHTTREE == 4) { map.SetBlockAt(cord.X+1,cord.Y,cord.Z,50); map.SetBlockAt(cord.X-1,cord.Y,cord.Z,50); if(LIGHTTREE == 4) { map.SetBlockAt(cord.X,cord.Y,cord.Z+1,50); map.SetBlockAt(cord.X,cord.Y,cord.Z-1,50); } } } }
/// <summary> /// Create a round section of type matidx in blocklist. /// </summary> /// <param name="map"></param> /// <param name="vCenter">the coordinates of the center block</param> /// <param name="radius">the radius of the section.</param> /// <param name="diraxis">The list index for the axis to make the section perpendicular to. 0 indicates the x axis, 1 the y, 2 the z. The section will extend along the other two axies.</param> /// <param name="mat">What to make the section out of</param> public void crossection(ref IMapHandler map, Vector3i vCenter, double radius, int diraxis, byte mat) { long[] centArray=vCenter.ToArray(); int rad = (int)(radius + .618d); int secidx1 = (diraxis - 1)%3; int secidx2 = (1 + diraxis)%3; int[] coord = new int []{0,0,0}; for(int off1 =-rad; off1<rad+1;off1++) { for(int off2 =-rad; off2<rad+1;off2++) { double thisdist = Math.Sqrt(Math.Pow((double)Math.Abs(off1)+.5d,2d) + Math.Pow((double)Math.Abs(off2) + .5d,2)); if(thisdist > radius) continue; int pri = (int)centArray[diraxis]; int sec1 = (int)centArray[secidx1] + off1; int sec2 = (int)centArray[secidx2] + off2; coord[diraxis] = pri; coord[secidx1] = sec1; coord[secidx2] = sec2; map.SetBlockAt(coord[0],coord[1],coord[2],mat); } } }
public override void MakeTrunk(ref IMapHandler map) { int starty = (int)Pos[1]; int midy = (int)(Pos[1]+(trunkheight*.382)); int topy = (int)(Pos[1]+(trunkheight + 0.5)); // In this method, x and z are the position of the trunk. long x = Pos[0]; long z = Pos[2]; double midrad = trunkradius * .8; double endrad = trunkradius * (1 - trunkheight/Height); if(endrad < 1.0) endrad = 1.0; if(midrad < endrad) midrad = endrad; List<Vector3i> rootbases = new List<Vector3i>(); // Make the root buttresses, if indicated double startrad; if(ROOTBUTTRESSES || SHAPE == "mangrove") { // The start radius of the trunk should be a little smaller if we // are using root buttresses. startrad = trunkradius * .8; // rootbases is used later in makeroots(...) as // starting locations for the roots. rootbases.Add(new Vector3i(x,z,(long)startrad)); double buttress_radius = trunkradius * 0.382; // posradius is how far the root buttresses should be offset // from the trunk. double posradius = trunkradius; // In mangroves, the root buttresses are much more extended. if(SHAPE == "mangrove") posradius = posradius *2.618; int num_of_buttresses = (int)(Math.Sqrt(trunkradius) + 3.5); for(int i = 0;i<num_of_buttresses;i++) { double rndang = rand.NextDouble()*2*Math.PI; double thisposradius = posradius * (0.9 + rand.NextDouble()*.2); // thisx and thisz are the x and z position for the base of // the root buttress. long thisx = x + (long)(thisposradius * Math.Sin(rndang)); long thisz = z + (long)(thisposradius * Math.Cos(rndang)); // thisbuttressradius is the radius of the buttress. // Currently, root buttresses do not taper. double thisbuttressradius = buttress_radius * (0.618 + rand.NextDouble()); if(thisbuttressradius < 1.0) thisbuttressradius = 1.0; // Make the root buttress. taperedlimb(ref map, new Vector3i(thisx,starty,thisz),new Vector3i(x,midy,z), (int)thisbuttressradius,(int)thisbuttressradius); // Add this root buttress as a possible location at // which roots can spawn. rootbases.Add(new Vector3i(thisx,thisz,(long)thisbuttressradius)); } }else{ // If root buttresses are turned off, set the trunk radius // to normal size. rootbases.Clear(); startrad=trunkradius; rootbases.Add(new Vector3i(x,z,(long)trunkradius)); } // Make the lower and upper sections of the trunk. taperedlimb(ref map, new Vector3i(x,starty,z), new Vector3i(x,midy,z),(int)startrad,(int)midrad); taperedlimb(ref map,new Vector3i(x,midy,z),new Vector3i(x,topy,z),(int)midrad,(int)endrad); // Make the branches makebranches(ref map); // Make the roots, if indicated. if (ROOTS == "yes" || ROOTS == "tostone" || ROOTS == "hanging") makeroots(ref map, rootbases); }
/// <summary> /// Create a tapered cylinder in blocklist. /// start and end are the beginning and ending coordinates of form [x,y,z]. /// startsize and endsize are the beginning and ending radius. /// The material of the cylinder is 17, which indicates wood in Minecraft. /// </summary> /// <param name="map"></param> /// <param name="start"></param> /// <param name="end"></param> /// <param name="startsize"></param> /// <param name="endsize"></param> public void taperedlimb(ref IMapHandler map, Vector3i vStart, Vector3i vEnd, int startsize, int endsize) { // delta is the coordinate vector for the difference between // start and end. Vector3i vDelta = vEnd - vStart; long[] delta = vDelta.ToArray(); long[] start = vStart.ToArray(); long[] end = vEnd.ToArray(); // primidx is the index (0,1,or 2 for x,y,z) for the coordinate // which has the largest overall delta. long maxdist = 0; int primidx = 0; for (int i = 0; i < 3; i++) { if (Math.Abs(delta[i]) > maxdist) { maxdist = delta[i]; primidx = i; } } if (maxdist == 0) { return; } // secidx1 and secidx2 are the remaining indicies out of [0,1,2]. int secidx1 = (primidx - 1) % 3; int secidx2 = (1 + primidx) % 3; // primsign is the digit 1 or -1 depending on whether the limb is headed // along the positive or negative primidx axis. long primsign = delta[primidx] / Math.Abs(delta[primidx]); // secdelta1 and ...2 are the amount the associated values change // for every step along the prime axis. long secdelta1 = delta[secidx1]; double secfac1 = (double)(secdelta1) / delta[primidx]; long secdelta2 = delta[secidx2]; double secfac2 = (double)(secdelta2) / delta[primidx]; // Initialize coord. These values could be anything, since // they are overwritten. long[] coord = new long[] { 0, 0, 0 }; // Loop through each crossection along the primary axis, // from start to end. long endoffset = delta[primidx] + primsign; for (long primoffset = 0; primoffset < endoffset; primoffset += primsign)//primoffset in range(0, endoffset, primsign): { long primloc = start[primidx] + primoffset; int secloc1 = (int)(start[secidx1] + primoffset * secfac1); int secloc2 = (int)(start[secidx2] + primoffset * secfac2); coord[primidx] = primloc; coord[secidx1] = secloc1; coord[secidx2] = secloc2; long primdist = Math.Abs(delta[primidx]); int radius = (int)(endsize + (startsize - endsize) * Math.Abs(delta[primidx] - primoffset) / primdist); crossection(ref map, new Vector3i(coord[0], coord[1], coord[2]), radius, primidx, 17); } }
public void makeroots(ref IMapHandler map, List<Vector3i> rootbases) { foreach(Vector3i coord in foliage_cords) { // First, set the threshhold for randomly selecting this // coordinate for root creation. double dist = Math.Sqrt( Math.Pow(coord[0]-Pos[0],2) + Math.Pow(coord[2]-Pos[2],2)); double ydist = coord[1]-Pos[1]; double value = (branchdensity * 220 * Height)/Math.Pow((ydist + dist), 3d); // Randomly skip roots, based on the above threshold if(value < rand.NextDouble()) continue; // initialize the internal variables from a selection of // starting locations. int ci = rand.Next(0, rootbases.Count-1); Vector3i rootbase = rootbases[ci]; long rootx = rootbase[0]; long rootz = rootbase[1]; double rootbaseradius = rootbase[2]; // Offset the root origin location by a random amount // (radialy) from the starting location. double rndr = (Math.Sqrt(rand.NextDouble())*rootbaseradius*.618); double rndang = rand.NextDouble()*2*Math.PI; int rndx = (int)(rndr*Math.Sin(rndang) + 0.5); int rndz = (int)(rndr*Math.Cos(rndang) + 0.5); int rndy = (int)(rand.NextDouble()*rootbaseradius*0.5); Vector3i startcoord = new Vector3i(rootx+rndx,Pos[1]+rndy,rootz+rndz); // offset is the distance from the root base to the root tip. Vector3i offset = startcoord-coord; // If this is a mangrove tree, make the roots longer. if(SHAPE == "mangrove") { offset = (offset * 1.618) - 1.5; } Vector3i endcoord = startcoord+offset; double rootstartsize = (rootbaseradius*0.618* Math.Abs(offset[1])/(Height*0.618)); if(rootstartsize < 1.0) rootstartsize = 1.0; double endsize = 1.0; // If ROOTS is set to "tostone" or "hanging" we need to check // along the distance for collision with existing materials. if(ROOTS == "tostone" || ROOTS == "hanging") { double offlength = Math.Sqrt( Math.Pow(offset[0],2) + Math.Pow(offset[1],2) + Math.Pow(offset[2],2)); if(offlength < 1) continue; double rootmid = endsize; // vec is a unit vector along the direction of the root. Vector3i vec = offset/offlength; byte searchindex; if(ROOTS == "tostone") searchindex = 1; else // Hanging searchindex = 0; // startdist is how many steps to travel before starting to // search for the material. It is used to ensure that large // roots will go some distance before changing directions // or stopping. double startdist = (int)(rand.NextDouble()*6*Math.Sqrt(rootstartsize) + 2.8); // searchstart is the coordinate where the search should begin Vector3i searchstart = (startcoord + startdist) * vec; // dist stores how far the search went (including searchstart) // before encountering the expected marterial. dist = startdist + map.DistanceToMaterial(searchstart,vec,searchindex); // If the distance to the materila is less than the length // of the root, change the end point of the root to where // the search found the material. if(dist < offlength) // rootmid is the size of the crossection at endcoord. rootmid += (rootstartsize - endsize)*(1-dist/offlength); // endcoord is the midpoint for hanging roots, // and the endpoint for roots stopped by stone. endcoord = startcoord+(vec*dist); if(ROOTS == "hanging") { // remaining_dist is how far the root had left // to go when it was stopped. double remaining_dist = offlength - dist; // Initialize bottomcord to the stopping point of // the root, and then hang straight down // a distance of remaining_dist. Vector3i bottomcord = endcoord; bottomcord.Y += -(long)remaining_dist; // Make the hanging part of the hanging root. taperedlimb(ref map, endcoord, bottomcord, (int)rootmid, (int)endsize); } // make the beginning part of hanging or "tostone" roots taperedlimb(ref map, startcoord, endcoord, (int)rootstartsize, (int)rootmid); // If you aren't searching for stone or air, just make the root. } else { taperedlimb(ref map, startcoord, endcoord, (int)rootstartsize, (int)endsize); } } }
/// <summary> /// Gen a dungeon /// </summary> /// <param name="CX">Chunk X pos</param> /// <param name="CY">Chunk Y pos</param> /// <param name="CH">Chunk Horizontal Scale</param> /// <param name="b"></param> /// <param name="mh"></param> /// <param name="r"></param> /// <param name="x"></param> /// <param name="y"></param> /// <param name="z"></param> /// <returns></returns> public static bool MakeDungeon(int CX, int CY, ref byte[, ,] b, ref IMapHandler mh, Random r) { int CH = (int)mh.ChunkScale.X; int CV = (int)mh.ChunkScale.Z; int x = r.Next(0+DungeonSizeX-1, CH-DungeonSizeX+1); int y = r.Next(0+DungeonSizeY-1, CH-DungeonSizeY+1); int z = r.Next(0+DungeonSizeZ-1, CV-DungeonSizeZ+1); Vector3i position = new Vector3i(x,y,z); //Console.WriteLine("Creating dungeon in {0}...", position); if (!CheckForDungeonSpace(b, x, y, z)) return false; Vector3i size = new Vector3i((DungeonSizeX*2)+1,(DungeonSizeY*2)+1,(DungeonSizeZ*2)+1); FillRect(ref b, 0, position, size); MakeDungeonWalls(ref b, r, position, size); mh.SetTileEntity(new MobSpawner(x+(int)(CX*CH), y+(int)(CY*CH), z-DungeonSizeZ+1, Entity.GetRandomMonsterID(r), 20)); b[x, y, z - DungeonSizeZ + 1]=52; return true; }
/// <summary> /// From the VoxelSim project /// http://github.com/N3X15/VoxelSim /// </summary> /// <param name="X"></param> /// <param name="Y"></param> /// <param name="chunksize"></param> /// <returns></returns> public override byte[, ,] Generate(ref IMapHandler mh, long X, long Y) { Vector3i chunksize = mh.ChunkScale; int ZH = (int)chunksize.Z; byte[, ,] b = new byte[chunksize.X, chunksize.Y, chunksize.Z]; bool[, ,] cavemap = new bool[chunksize.X, chunksize.Y, chunksize.Z]; byte Sand=12; byte Grass=2; byte Soil=3; byte Water=9; if (HellMode) { Sand = 49; // Obsidian Grass = Soil; Water = 11; // Lava } for (int z = 0; z < ZH; z++) { for (int x = 0; x < chunksize.X; x++) { for (int y = 0; y < chunksize.Y; y++) { //Console.WriteLine("HeightOffset {0}",heightoffset); cavemap[x, y, z] = false; if (z == 0) b[x, y, z] = 7; // Adminite layer else { double _do = ((CaveNoise.GetValue(x + (X * chunksize.X), y + (Y * chunksize.Y), z * 2.0) + 1) / 2.0); bool d3 = _do > CaveThreshold; // XOR? if(z<=WaterHeight+7)//if (!(!d1 || !d2)) { //Console.Write("#"); b[x, y, z] = (d3) ? b[x,y,z] : (byte)1; cavemap[x, y, z] = d3; //if (x == 0|| y == 0) // b[x, y, z] = 41; } else if (z == 1) b[x, y, z] = 11; } } } } //Console.WriteLine("Done generating chunk. [{0},{1}]",min,max); // Add soil, sand for (int x = 0; x < chunksize.X; x++) { //Console.WriteLine(); for (int y = 0; y < chunksize.Y; y++) { bool HavePloppedGrass = false; bool HaveTouchedSoil = false; byte BlockForThisColumn = 0; for (int z = (int)chunksize.Z - 1; z > 0; z--) { if (b[x, y, z] == 1) { HaveTouchedSoil=true; if (z + DERT_DEPTH >= ZH) continue; byte ddt = b[x, y, z + DERT_DEPTH]; switch (ddt) { case 0: // Air case 8: // Water case 9: // Water if (BlockForThisColumn == 0) { if (z - DERT_DEPTH <= WaterHeight) { b[x, y, z] = Sand; // Sand BlockForThisColumn = Sand; } else { b[x, y, z] = (HavePloppedGrass) ? Soil : Grass; // Dirt or grass if (!HavePloppedGrass) { BlockForThisColumn = Soil; HavePloppedGrass = true; } } } else { b[x, y, z] = BlockForThisColumn; } break; default: z = 0; break; } } // Place water else if (b[x, y, z] == 0 && z <= WaterHeight && !HaveTouchedSoil) { b[x, y, z] = (cavemap[x,y,z]) ? Soil:Water; } } } } for (int x = 0; x < chunksize.X; x++) { for (int y = 0; y < chunksize.Y; y++) { int z = 1; // TODO Yell at Notch for not making Lava occlude. :| if (b[x, y, z] == 0) b[x, y, z] = 11; // Lava for air. else if (b[x, y, z] == 9) b[x, y, z] = 49; // Obsidian for underwater shit. } } if (rand.Next(0, 10) == 0) { int DungeonTries = 128; while (!Utils.MakeDungeon((int)X, (int)Y, ref b, ref mh, rand)) { //Console.WriteLine("Making dungeon..."); if (DungeonTries-- == 0) break; } } /* int StillWater = 0; int RunningWater = 0; for (int z = 0; z < ZH; z++) { for (int x = 0; x < chunksize.X; x++) { for (int y = 0; y < chunksize.Y; y++) { switch (b[x, y, z]) { case 8: RunningWater++; break; case 9: StillWater++; break; default: break; } } } } Console.WriteLine("{0} still water, {1} running water", StillWater, RunningWater);*/ AddTrees(ref b, (int)X, (int)Y, (int)chunksize.Z); return b; }
public override void DoSkyLighting(IMapHandler _mh, long X, long Y) { Chunk c = _mh.GetChunk(X, Y); if (c == null) return; this.DoSkylighting(c); }