// Code to run when used by a player public override void Use(Player p, string message) { if (message != "") { string[] parameters = message.Split(' '); // Grab the parameters from the player's message if (parameters.Length == 5) // make sure there are 5 params { switch (parameters[4]) { case "flat": case "pixel": case "island": case "mountains": case "ocean": case "forest": break; default: p.SendMessage("Valid types: island, mountains, forest, ocean, flat, pixel"); return; } string name = parameters[0]; // create a new level... try { Level lvl = new Level(name, Convert.ToUInt16(parameters[1]), Convert.ToUInt16(parameters[2]), Convert.ToUInt16(parameters[3]), parameters[4]); lvl.changed = true; } finally { GC.Collect(); GC.WaitForPendingFinalizers(); } Player.GlobalMessage("Level " + name + " created"); } else { p.SendMessage("Not enough parameters! <name> <x> <y> <z> <type>"); } } else { Help(p); } if (Properties.ValidString(message, " ")) { } else { p.SendMessage("Please use an alphanumerical characters only!"); } }
//return true if tree is near private bool TreeCheck(Level Lvl, ushort x, ushort z, ushort y, short dist) { for (short xx = (short)-dist; xx <= +dist; ++xx) { for (short yy = (short)-dist; yy <= +dist; ++yy) { for (short zz = (short)-dist; zz <= +dist; ++zz) { if (Lvl.GetTile((ushort)(x + xx), (ushort)(z + zz ), (ushort)(y + yy)) == Block.trunk) { return true; } } } } return false; }
//Forces the edge of a map to slope lower for island map types float NegateEdge(ushort x, ushort y, Level Lvl) { float tempx = 0.0f, tempy = 0.0f; float temp; if (x != 0) { tempx = ((float)x / (float)Lvl.width) * 0.5f; } if (y != 0) { tempy = ((float)y / (float)Lvl.height) * 0.5f; } tempx = Math.Abs(tempx - 0.25f); tempy = Math.Abs(tempy - 0.25f); if (tempx > tempy) { temp = tempx - 0.15f; } else { temp = tempy - 0.15f; } //s.Log("temp = " + temp.ToString()); if (temp > 0.0f) { return temp; } return 0.0f; }
//returns the valve of a x,y terrain coordinate float GetPixel(ushort x, ushort y, Level Lvl) { if (x < 0) { return 0.0f; } if (x >= Lvl.width) { return 0.0f; } if (y < 0) { return 0.0f; } if (y >= Lvl.height) { return 0.0f;} divide += 1.0f; return terrain[x + y * Lvl.width]; }
//Averages over 9 points float GetAverage9(ushort x, ushort y, Level Lvl) { divide = 0.0f; float temp = GetPixel(x, y, Lvl); temp += GetPixel((ushort)(x + 1), y, Lvl); temp += GetPixel((ushort)(x - 1), y, Lvl); temp += GetPixel(x, (ushort)(y + 1), Lvl); temp += GetPixel(x, (ushort)(y - 1), Lvl); temp += GetPixel((ushort)(x + 1), (ushort)(y + 1), Lvl); temp += GetPixel((ushort)(x - 1), (ushort)(y + 1), Lvl); temp += GetPixel((ushort)(x + 1), (ushort)(y - 1), Lvl); temp += GetPixel((ushort)(x - 1), (ushort)(y - 1), Lvl); return temp / divide; }
void GeneratePerlinNoise(float[] array, Level Lvl, string type, Random rand) { GenerateNormalized(array, 0.7f, 8, Lvl.width, Lvl.height, rand.Next(), 64); }
public bool GenerateMap(Level Lvl, string type) { Logger.Log("Attemping to generate a map. Type: " + type); if (Inuse) { Logger.Log("Generator in use", LogType.Warning); return false; } Random rand = new System.Random(); try { Inuse = true; terrain = new float[Lvl.width * Lvl.height]; overlay = new float[Lvl.width * Lvl.height]; if (!type.Equals("ocean")) { overlay2 = new float[Lvl.width * Lvl.height]; } //float dispAux, pd; ushort WaterLevel = (ushort)(Lvl.depth / 2 + 2); if (type.Equals("ocean")) { WaterLevel = (ushort)(Lvl.depth * 0.85f); } //Generate the level GenerateFault(terrain, Lvl, type, rand); //APPLY FILTER to terrain FilterAverage(Lvl); //CREATE OVERLAY //GenerateFault(overlay, Lvl, "overlay", rand); Logger.Log("Creating overlay", LogType.Debug); GeneratePerlinNoise(overlay, Lvl, "", rand); if (!type.Equals("ocean")) { Logger.Log("Planning trees", LogType.Debug); GeneratePerlinNoise(overlay2, Lvl, "", rand); } Logger.Log("Converting height map", LogType.Debug); Logger.Log("And applying overlays", LogType.Debug); float RangeLow = 0.2f; float RangeHigh = 0.8f; float TreeDens = 0.35f; short TreeDist = 3; //changes the terrain range based on type, also tree threshold switch(type) { case "island": RangeLow = 0.4f; RangeHigh = 0.75f; break; case "forest": RangeLow = 0.45f; RangeHigh = 0.8f; TreeDens = 0.7f; TreeDist = 2; break; case "mountains": RangeLow = 0.3f; RangeHigh = 0.9f; TreeDist = 4; break; case "ocean": RangeLow = 0.1f; RangeHigh = 0.6f; break; default: break; } //loops though evey X/Z coordinate for ( int bb = 0; bb < terrain.Length; bb++) { ushort x = (ushort)(bb % Lvl.width); ushort y = (ushort)(bb / Lvl.width); ushort z; if (type.Equals("island")) //apply the edge dip { z = Evaluate(Lvl, Range(terrain[bb], RangeLow - NegateEdge(x, y, Lvl), RangeHigh - NegateEdge(x, y, Lvl))); } else { z = Evaluate(Lvl, Range(terrain[bb], RangeLow, RangeHigh)); } if (z > WaterLevel) { for (ushort zz = 0; z - zz >= 0; zz++) { if (overlay[bb] < 0.72f) //If not zoned for rocks or gravel { if (type.Equals("island")) //increase sand height for island { if (z > WaterLevel + 2) { if (zz == 0) { Lvl.Blockchange(x, (ushort)(z - zz), y, Block.grass); } //top layer else if (zz < 3) { Lvl.Blockchange(x, (ushort)(z - zz), y, Block.dirt); } //next few else { Lvl.Blockchange(x, (ushort)(z - zz), y, Block.rock); } //ten rock it } else { Lvl.Blockchange(x, (ushort)(z - zz), y, Block.sand); //SAAAND extra for islands } } else { if (zz == 0) { Lvl.Blockchange(x, (ushort)(z - zz), y, Block.grass); } else if (zz < 3) { Lvl.Blockchange(x, (ushort)(z - zz), y, Block.dirt); } else { Lvl.Blockchange(x, (ushort)(z - zz), y, Block.rock); } } } else { Lvl.Blockchange(x, (ushort)(z - zz), y, Block.rock); //zoned for above sea level rock floor } } if (overlay[bb] < 0.25f) //Zoned for flowers { int temprand = rand.Next(12); switch (temprand) { case 10: Lvl.Blockchange(x, (ushort)(z + 1), y, Block.redflower); break; case 11: Lvl.Blockchange(x, (ushort)(z + 1), y, Block.yellowflower); break; default: break; } } if (!type.Equals("ocean")) //Oceans dont have trees { if (overlay[bb] < 0.65f && overlay2[bb] < TreeDens) //If not a rock zoned area and is zoned for possible trees { if (Lvl.GetTile(x, (ushort)(z + 1), y) == Block.air) //No flowers here right? { if (Lvl.GetTile(x, z, y) == Block.grass) //Im not on sand am I either? { if (rand.Next(13) == 0) { if (!TreeCheck(Lvl, x, z, y, TreeDist)) //Am I too close to other trees? { AddTree(Lvl, x, (ushort)(z + 1), y, rand); } } } } } } } else //Must be on/under the water line then { for (ushort zz = 0; WaterLevel - zz >= 0; zz++) { if (WaterLevel - zz > z) {Lvl.Blockchange(x, (ushort)(WaterLevel - zz), y, Block.water);} //better fill the water aboce me else if (WaterLevel - zz > z-3) { if (overlay[bb] < 0.75f) { Lvl.Blockchange(x, (ushort)(WaterLevel - zz), y, Block.sand); //sand top } else { Lvl.Blockchange(x, (ushort)(WaterLevel - zz), y, Block.gravel); //zoned for gravel } } else {Lvl.Blockchange(x, (ushort)(WaterLevel - zz), y, Block.rock);} } } } } catch { Logger.Log("Map Generator Failed", LogType.Error); Inuse = false; return false; } terrain = new float[0]; //Derp overlay = new float[0]; //Derp overlay2 = new float[0]; //Derp Inuse = false; return true; }
void GenerateFault(float[] array,Level Lvl, string type, Random rand) { float startheight = 0.5f; float dispAux; ushort i, j, k, halfX, halfZ; float a, b, c, w, d; float DispMax, DispMin, DispChange; DispMax = 0.01f; DispChange = -0.0025f; if (type.Equals("mountains")) { DispMax = 0.02f; startheight = 0.6f; } else if (type.Equals("overlay")) { DispMax = 0.02f; DispChange = -0.01f; } for (int x = 0; x < array.Length; x++) { array[x] = startheight; //overlay[x] = 0.5f; } DispMin = -DispMax; float disp = DispMax; //if (terrainHeights == NULL) // return (TERRAIN_ERROR_NOT_INITIALISED); halfX = (ushort)(Lvl.width / 2); halfZ = (ushort)(Lvl.height / 2); int numIterations = (int)((Lvl.width + Lvl.height)); Logger.Log("Iterations = " + numIterations.ToString(), LogType.Debug); for (k = 0; k < numIterations; k++) { //s.Log("itteration " + k.ToString()); d = (float)Math.Sqrt(halfX * halfX + halfZ * halfZ); w = (float)(rand.NextDouble() * 360); //w = (float)(rand.NextDouble()*90); a = (float)Math.Cos(w); b = (float)Math.Sin(w); c = ((float)rand.NextDouble()) * 2 * d - d; //c = ((float)rand.NextDouble() / 1) * 2 * d - d; //float disp = (float)(rand.NextDouble()* 0.02f - 0.01f); //iterationsDone++; //if (iterationsDone < itMinDisp) // disp = maxDisp + (iterationsDone / (itMinDisp + 0.0)) * (minDisp - maxDisp); //else // disp = minDisp; for (i = 0; i < Lvl.height; i++) { for (j = 0; j < Lvl.width; j++) { //switch (terrainFunction) //{ //case STEP: if ((i - halfZ) * a + (j - halfX) * b + c > 0) dispAux = disp; else dispAux = -disp; // break; /*case SIN: pd = ((i - halfZ) * a + (j - halfX) * b + c) / terrainWaveSize; if (pd > 1.57) pd = 1.57; else if (pd < 0) pd = 0; dispAux = -disp / 2 + sin(pd) * disp; break; case COS: pd = ((i - halfZ) * a + (j - halfX) * b + c) / terrainWaveSize; if (pd > 3.14) pd = 3.14; else if (pd < -3.14) pd = -3.14; dispAux = disp - (terrainWaveSize / (terrainGridWidth + 0.0)) + cos(pd) * disp; break; }*/ //s.Log("adding " + dispAux.ToString()); AddTerrainHeight(array, j, i, Lvl.width, dispAux); //terrainHeights[i * terrainGridWidth + j] += dispAux; } } disp += DispChange; if (disp < DispMin) { disp = DispMax; } } }
//applys the average filter void FilterAverage(Level Lvl) { Logger.Log("Applying average filtering", LogType.Debug); float[] filtered = new float[terrain.Length]; for (int bb = 0; bb < terrain.Length; bb++) { ushort x = (ushort)(bb % Lvl.width); ushort y = (ushort)(bb / Lvl.width); filtered[bb] = GetAverage9(x, y, Lvl); } for (int bb = 0; bb < terrain.Length; bb++) { terrain[bb] = filtered[bb]; } }
//converts the float into a ushort for map height ushort Evaluate(Level lvl, float height) { ushort temp = (ushort)(height * lvl.depth); if (temp < 0) return 0; if (temp > lvl.depth - 1) return (ushort)(lvl.depth - 1); return temp; }
// void AddTree(Level Lvl, ushort x, ushort z, ushort y, Random Rand) { byte height = (byte)Rand.Next(4, 7); for (ushort zz = 0; zz < height; zz++) { if (Lvl.GetTile(x, (ushort)(z + zz), y) == Block.air) //Not likly to trigger anyway { Lvl.Blockchange(x, (ushort)(z + zz), y, Block.trunk); } else { height = (byte)zz; } } short top = (short)(height - 3); for (short xx = (short)-top; xx <= top; ++xx) { for (short yy = (short)-top; yy <= top; ++yy) { for (short zz = (short)-top; zz <= top; ++zz) { if (Lvl.GetTile((ushort)(x + xx), (ushort)(z + zz + height), (ushort)(y + yy)) == Block.air) //Not likly to trigger anyway { //short Dist = (short)(Math.Abs(xx) + Math.Abs(yy) + Math.Abs(zz)); short Dist = (short)(Math.Sqrt(xx * xx + yy * yy + zz * zz)); if (Dist < top + 1) { if (Rand.Next((int)(Dist)) < 2) { Lvl.Blockchange((ushort)(x + xx), (ushort)(z + zz + height), (ushort)(y + yy), Block.leaf); } } } } } } }
void SetupLevels() { levels = new List<Level>(Properties.MaxMaps); MapGen = new MapGenerator(); Random random = new Random(); if (File.Exists("levels/" + Properties.MainLevel + ".lvl")) { mainLevel = Level.Load(Properties.MainLevel); if (mainLevel == null) { if (File.Exists("levels/" + Properties.MainLevel + ".lvl.backup")) { Logger.Log("Atempting to load backup.", LogType.Debug); File.Copy("levels/" + Properties.MainLevel + ".lvl.backup", "levels/" + Properties.MainLevel + ".lvl", true); mainLevel = Level.Load(Properties.MainLevel); if (mainLevel == null) { Logger.Log("BACKUP FAILED!", LogType.Error); } } else { Logger.Log("BACKUP NOT FOUND!", LogType.Error); } } } else { Logger.Log("Warning: No main.lvl found.", LogType.Debug); Logger.Log("Creating Default main.lvl", LogType.Debug); mainLevel = new Level(Properties.MainLevel, 128, 64, 128, "flat"); mainLevel.permissionvisit = LevelPermission.Guest; mainLevel.permissionbuild = LevelPermission.Guest; mainLevel.Save(); } levels.Add(mainLevel); if (File.Exists("autoload.txt")) { try { string[] lines = File.ReadAllLines("autoload.txt"); foreach (string line in lines) { //int temp = 0; string _line = line.Trim(); try { if (_line == "") { continue; } if (_line[0] == '#') { continue; } int index = _line.IndexOf("="); string key = line.Split('=')[0].Trim(); string value; try { value = line.Split('=')[1].Trim(); } catch { value = "0"; } if (!key.Equals("main")) { Command.all.Find("load").Use(key + " " + value); } else // Main's already loaded so we just check and set the physics level { try { int temp = int.Parse(value); if (temp >= 0 && temp <= 2) { mainLevel.physics = temp; } } catch { Logger.Log("The Physics variable for main in autoload.txt is invalid!", LogType.Warning); } } } catch (Exception ex) { Logger.Log(_line + " failed.", LogType.Error); Logger.Log(ex.Message, LogType.ErrorMessage); } } } catch { Logger.Log("autoload.txt error", LogType.Error); } GC.Collect(); GC.WaitForPendingFinalizers(); } else { Logger.Log("autoload.txt does not exist", LogType.Debug); } }
public static void GlobalMessageLevel(Level l, string message) { players.ForEach(delegate(Player p) { if (p.level == l) p.SendMessage(message); }); }
public static Level Load(string name, byte phys) { Level level = null; string path = "levels/" + name + ".lvl"; if (File.Exists(path)) { FileStream fs = File.OpenRead(path); try { GZipStream gs = new GZipStream(fs, CompressionMode.Decompress); byte[] ver = new byte[2]; gs.Read(ver, 0, ver.Length); ushort version = BitConverter.ToUInt16(ver, 0); if (version == 1875) { } else if (version == 1874) { byte[] header = new byte[16]; gs.Read(header, 0, header.Length); ushort width = BitConverter.ToUInt16(header, 0); ushort height = BitConverter.ToUInt16(header, 2); ushort depth = BitConverter.ToUInt16(header, 4); level = new Level(name, width, depth, height, "empty"); level.spawnx = BitConverter.ToUInt16(header, 6); level.spawnz = BitConverter.ToUInt16(header, 8); level.spawny = BitConverter.ToUInt16(header, 10); level.rotx = header[12]; level.roty = header[13]; level.permissionvisit = (LevelPermission)header[14]; level.permissionbuild = (LevelPermission)header[15]; } else { byte[] header = new byte[12]; gs.Read(header, 0, header.Length); ushort width = version; ushort height = BitConverter.ToUInt16(header, 0); ushort depth = BitConverter.ToUInt16(header, 2); level = new Level(name, width, depth, height, "empty"); level.spawnx = BitConverter.ToUInt16(header, 4); level.spawnz = BitConverter.ToUInt16(header, 6); level.spawny = BitConverter.ToUInt16(header, 8); level.rotx = header[10]; level.roty = header[11]; } level.physics = phys; byte[] blocks = new byte[level.width * level.height * level.depth]; gs.Read(blocks, 0, blocks.Length); for (int i = 0; i < level.width * level.height * level.depth; ++i) { level.blocks[i] = blocks[i]; } gs.Close(); Logger.Log("LOADED: Level \"" + name + "\"."); level.backedup = true; } catch (Exception ex) { Logger.Log("ERROR loading level \"" + name + "\".", LogType.Error); Logger.Log(ex.StackTrace, LogType.ErrorMessage); level = null; } finally { fs.Close(); } } else { Logger.Log("ERROR loading level \"" + name + "\".", LogType.Error); level = null; } return level; }