Memory optimisations in /fill, also only store delta time for undo positions to further save memory.

This commit is contained in:
UnknownShadow200 2016-02-12 15:08:34 +11:00
parent af3fe2c76d
commit 87758df1e3
13 changed files with 62 additions and 52 deletions

View File

@ -86,7 +86,8 @@ namespace MCGalaxy.Commands
foundOne = true; foundOne = true;
Deleted = inCache[i].deleted; Deleted = inCache[i].deleted;
Username = inCache[i].name; Username = inCache[i].name;
TimePerformed = inCache[i].TimePerformed.ToString("yyyy-MM-dd HH:mm:ss"); DateTime time = Server.StartTimeLocal.AddSeconds(inCache[i].timeDelta);
TimePerformed = time.ToString("yyyy-MM-dd HH:mm:ss");
BlockUsed = Block.Name(inCache[i].type); BlockUsed = Block.Name(inCache[i].type);
if (!Deleted) if (!Deleted)

View File

@ -67,19 +67,19 @@ namespace MCGalaxy.Commands {
static void HighlightOnline(Player p, long seconds, Player who) { static void HighlightOnline(Player p, long seconds, Player who) {
for (int i = who.UndoBuffer.Count - 1; i >= 0; --i) { for (int i = who.UndoBuffer.Count - 1; i >= 0; --i) {
try { try {
Player.UndoPos Pos = who.UndoBuffer[i]; Player.UndoPos undo = who.UndoBuffer[i];
Level foundLevel = LevelInfo.FindExact(Pos.mapName); Level foundLevel = LevelInfo.FindExact(undo.mapName);
if (foundLevel != p.level) continue; if (foundLevel != p.level) continue;
byte b = foundLevel.GetTile(Pos.x, Pos.y, Pos.z); byte b = foundLevel.GetTile(undo.x, undo.y, undo.z);
if (Pos.timePlaced.AddSeconds(seconds) < DateTime.Now) DateTime time = Server.StartTime.AddSeconds(undo.timeDelta + seconds);
break; if (time < DateTime.UtcNow) break;
if (b == Pos.newtype || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) { if (b == undo.newtype || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
if (b == Block.air || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) if (b == Block.air || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava)
p.SendBlockchange(Pos.x, Pos.y, Pos.z, Block.red); p.SendBlockchange(undo.x, undo.y, undo.z, Block.red);
else else
p.SendBlockchange(Pos.x, Pos.y, Pos.z, Block.green); p.SendBlockchange(undo.x, undo.y, undo.z, Block.green);
} }
} catch { } } catch { }
} }

View File

@ -66,13 +66,14 @@ namespace MCGalaxy.Commands {
if (!Block.canPlace(p, oldType) && !Block.BuildIn(oldType)) { Player.SendMessage(p, "Cannot fill with that."); return; } if (!Block.canPlace(p, oldType) && !Block.BuildIn(oldType)) { Player.SendMessage(p, "Cannot fill with that."); return; }
SparseBitSet bits = new SparseBitSet(p.level.Width, p.level.Height, p.level.Length); SparseBitSet bits = new SparseBitSet(p.level.Width, p.level.Height, p.level.Length);
List<FillPos> buffer = new List<FillPos>(), origins = new List<FillPos>(); List<int> buffer = new List<int>(), origins = new List<int>();
FloodFill(p, x, y, z, oldType, oldExtType, cpos.solid, bits, buffer, origins, 0); FloodFill(p, x, y, z, oldType, oldExtType, cpos.solid, bits, buffer, origins, 0);
int totalFill = origins.Count; int totalFill = origins.Count;
for (int i = 0; i < totalFill; i++) { for (int i = 0; i < totalFill; i++) {
FillPos pos = origins[i]; int pos = origins[i];
FloodFill(p, pos.X, pos.Y, pos.Z, oldType, oldExtType, cpos.solid, bits, buffer, origins, 0); p.level.IntToPos(pos, out x, out y, out z);
FloodFill(p, x, y, z, oldType, oldExtType, cpos.solid, bits, buffer, origins, 0);
totalFill = origins.Count; totalFill = origins.Count;
} }
@ -91,14 +92,12 @@ namespace MCGalaxy.Commands {
protected override void Blockchange2(Player p, ushort x, ushort y, ushort z, byte type, byte extType) { } protected override void Blockchange2(Player p, ushort x, ushort y, ushort z, byte type, byte extType) { }
void FloodFill(Player p, ushort x, ushort y, ushort z, byte oldType, byte oldExtType, SolidType fillType, void FloodFill(Player p, ushort x, ushort y, ushort z, byte oldType, byte oldExtType, SolidType fillType,
SparseBitSet bits, List<FillPos> buffer, List<FillPos> origins, int depth) { SparseBitSet bits, List<int> buffer, List<int> origins, int depth) {
FillPos pos;
pos.X = x; pos.Y = y; pos.Z = z;
if (bits.Get(x, y, z)) return; if (bits.Get(x, y, z)) return;
int index = p.level.PosToInt(x, y, z);
if (depth > 2000) { origins.Add(pos); return; } if (depth > 2000) { origins.Add(index); return; }
bits.Set(x, y, z, true); bits.Set(x, y, z, true);
buffer.Add(pos); buffer.Add(index);
if (fillType != SolidType.verticalX) { // x if (fillType != SolidType.verticalX) { // x
if (CheckTile(p, (ushort)(x + 1), y, z, oldType, oldExtType)) if (CheckTile(p, (ushort)(x + 1), y, z, oldType, oldExtType))
@ -131,9 +130,8 @@ namespace MCGalaxy.Commands {
if (tile == oldTile && tile == Block.custom_block) { if (tile == oldTile && tile == Block.custom_block) {
byte extTile = p.level.GetExtTile(x, y, z); byte extTile = p.level.GetExtTile(x, y, z);
return extTile == oldExtTile; return extTile == oldExtTile;
} else {
return tile == oldTile;
} }
return tile == oldTile;
} }
public override void Help(Player p) { public override void Help(Player p) {

View File

@ -44,7 +44,7 @@ namespace MCGalaxy.Commands {
lvl.Blockchange(p, Pos.x, Pos.y, Pos.z, Pos.type, Pos.extType); lvl.Blockchange(p, Pos.x, Pos.y, Pos.z, Pos.type, Pos.extType);
Pos.newtype = Pos.type; Pos.newExtType = Pos.extType; Pos.newtype = Pos.type; Pos.newExtType = Pos.extType;
Pos.type = type; Pos.extType = extType; Pos.type = type; Pos.extType = extType;
Pos.timePlaced = DateTime.Now; Pos.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
p.UndoBuffer.Add(Pos); p.UndoBuffer.Add(Pos);
} }

View File

@ -164,8 +164,8 @@ namespace MCGalaxy.Commands
Level lvl = LevelInfo.FindExact(undo.mapName); Level lvl = LevelInfo.FindExact(undo.mapName);
saveLevel = lvl; saveLevel = lvl;
byte b = lvl.GetTile(undo.x, undo.y, undo.z); byte b = lvl.GetTile(undo.x, undo.y, undo.z);
if (undo.timePlaced.AddSeconds(seconds) < DateTime.Now) DateTime time = Server.StartTime.AddSeconds(undo.timeDelta + seconds);
return false; if (time < DateTime.UtcNow) return false;
if (b == undo.newtype || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) { if (b == undo.newtype || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
undo.newtype = undo.type; undo.newExtType = undo.extType; undo.newtype = undo.type; undo.newExtType = undo.extType;

View File

@ -24,7 +24,7 @@ namespace MCGalaxy {
public class FillDrawOp : DrawOp { public class FillDrawOp : DrawOp {
public List<FillPos> Positions; public List<int> Positions;
public override string Name { get { return "Fill"; } } public override string Name { get { return "Fill"; } }
@ -34,8 +34,10 @@ namespace MCGalaxy {
public override void Perform(ushort x1, ushort y1, ushort z1, ushort x2, public override void Perform(ushort x1, ushort y1, ushort z1, ushort x2,
ushort y2, ushort z2, Player p, Level lvl, Brush brush) { ushort y2, ushort z2, Player p, Level lvl, Brush brush) {
foreach (FillPos pos in Positions) { ushort x, y, z;
PlaceBlock(p, lvl, pos.X, pos.Y, pos.Z, brush); foreach (int pos in Positions) {
lvl.IntToPos(pos, out x, out y, out z);
PlaceBlock(p, lvl, x, y, z, brush);
} }
} }
} }

View File

@ -65,7 +65,7 @@ namespace MCGalaxy {
for (int c = 0; c < count; c++) { for (int c = 0; c < count; c++) {
block item = l.blockqueue[c]; block item = l.blockqueue[c];
bP.name = item.p.name; bP.name = item.p.name;
bP.TimePerformed = DateTime.Now; bP.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
ushort x, y, z; ushort x, y, z;
l.IntToPos(item.index, out x, out y, out z); l.IntToPos(item.index, out x, out y, out z);

View File

@ -144,7 +144,7 @@ namespace MCGalaxy {
Level.BlockPos bP; Level.BlockPos bP;
bP.name = p.name; bP.name = p.name;
bP.TimePerformed = DateTime.Now; bP.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
bP.index = b; bP.index = b;
bP.type = type; bP.type = type;
bP.extType = extType; bP.extType = extType;
@ -156,7 +156,7 @@ namespace MCGalaxy {
Pos.mapName = this.name; Pos.mapName = this.name;
Pos.type = oldType; Pos.extType = oldExtType; Pos.type = oldType; Pos.extType = oldExtType;
Pos.newtype = type; Pos.newExtType = extType; Pos.newtype = type; Pos.newExtType = extType;
Pos.timePlaced = DateTime.Now; Pos.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
p.UndoBuffer.Add(Pos); p.UndoBuffer.Add(Pos);
} }
@ -324,7 +324,7 @@ namespace MCGalaxy {
Pos.mapName = name; Pos.mapName = name;
Pos.type = b; Pos.extType = extB; Pos.type = b; Pos.extType = extB;
Pos.newtype = type; Pos.newExtType = extType; Pos.newtype = type; Pos.newExtType = extType;
Pos.timePlaced = DateTime.Now; Pos.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
p.UndoBuffer.Add(Pos); p.UndoBuffer.Add(Pos);
errorLocation = "Setting tile"; errorLocation = "Setting tile";

View File

@ -350,8 +350,8 @@ namespace MCGalaxy
BlockPos bP = tempCache[i]; BlockPos bP = tempCache[i];
int deleted = bP.deleted ? 1 : 0; int deleted = bP.deleted ? 1 : 0;
IntToPos(bP.index, out x, out y, out z); IntToPos(bP.index, out x, out y, out z);
string query = String.Format(template, bP.name, DateTime time = Server.StartTimeLocal.AddSeconds(bP.timeDelta);
bP.TimePerformed.ToString("yyyy-MM-dd HH:mm:ss"), string query = String.Format(template, bP.name, time.ToString("yyyy-MM-dd HH:mm:ss"),
x, y, z, bP.type, deleted); x, y, z, bP.type, deleted);
if (!transaction.Execute(query)) { if (!transaction.Execute(query)) {
transaction.Rollback(); return; transaction.Rollback(); return;
@ -680,13 +680,12 @@ namespace MCGalaxy
return PlayerInfo.players.Where(p => p.level == this).ToList(); return PlayerInfo.players.Where(p => p.level == this).ToList();
} }
public struct BlockPos public struct BlockPos {
{ public string name;
public DateTime TimePerformed; public int timeDelta;
public string name; public int index;
public int index;
public bool deleted;
public byte type, extType; public byte type, extType;
public bool deleted;
} }
public struct UndoPos { public struct UndoPos {

View File

@ -238,7 +238,7 @@ namespace MCGalaxy {
} }
//Undo //Undo
public struct UndoPos { public ushort x, y, z; public byte type, extType, newtype, newExtType; public string mapName; public DateTime timePlaced; } public struct UndoPos { public ushort x, y, z; public byte type, extType, newtype, newExtType; public string mapName; public int timeDelta; }
public List<UndoPos> UndoBuffer = new List<UndoPos>(); public List<UndoPos> UndoBuffer = new List<UndoPos>();
public List<UndoPos> RedoBuffer = new List<UndoPos>(); public List<UndoPos> RedoBuffer = new List<UndoPos>();
@ -1000,7 +1000,7 @@ namespace MCGalaxy {
Level.BlockPos bP; Level.BlockPos bP;
bP.name = name; bP.name = name;
bP.TimePerformed = DateTime.Now; bP.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
bP.index = level.PosToInt(x, y, z); bP.index = level.PosToInt(x, y, z);
bP.type = type; bP.type = type;
bP.extType = extType; bP.extType = extType;

View File

@ -35,7 +35,8 @@ namespace MCGalaxy.Util {
ChunkHeader lastChunk = default(ChunkHeader); ChunkHeader lastChunk = default(ChunkHeader);
foreach (Player.UndoPos uP in buffer) { foreach (Player.UndoPos uP in buffer) {
int timeDiff = (int)(uP.timePlaced - lastChunk.BaseTime).TotalSeconds; DateTime time = Server.StartTime.AddSeconds(uP.timeDelta);
int timeDiff = (int)(time - lastChunk.BaseTime).TotalSeconds;
if (lastChunk.LevelName != uP.mapName || timeDiff > 65535 || lastChunk.Entries == ushort.MaxValue) { if (lastChunk.LevelName != uP.mapName || timeDiff > 65535 || lastChunk.Entries == ushort.MaxValue) {
WriteChunkEntries(w, lastChunk.Entries, entriesPos); WriteChunkEntries(w, lastChunk.Entries, entriesPos);
lastChunk = WriteEmptyChunk(w, uP, ref entriesPos); lastChunk = WriteEmptyChunk(w, uP, ref entriesPos);
@ -66,7 +67,8 @@ namespace MCGalaxy.Util {
Pos.mapName = chunk.LevelName; Pos.mapName = chunk.LevelName;
for (int j = 0; j < chunk.Entries; j++ ) { for (int j = 0; j < chunk.Entries; j++ ) {
Pos.timePlaced = chunk.BaseTime.AddSeconds(r.ReadUInt16()); DateTime rawTime = chunk.BaseTime.AddSeconds(r.ReadUInt16());
Pos.timeDelta = (int)rawTime.Subtract(Server.StartTime).TotalSeconds;
Pos.x = r.ReadUInt16(); Pos.y = r.ReadUInt16(); Pos.z = r.ReadUInt16(); Pos.x = r.ReadUInt16(); Pos.y = r.ReadUInt16(); Pos.z = r.ReadUInt16();
Pos.type = r.ReadByte(); Pos.extType = r.ReadByte(); Pos.type = r.ReadByte(); Pos.extType = r.ReadByte();
Pos.newtype = r.ReadByte(); Pos.newExtType = r.ReadByte(); Pos.newtype = r.ReadByte(); Pos.newExtType = r.ReadByte();
@ -78,7 +80,8 @@ namespace MCGalaxy.Util {
protected override bool UndoEntry(Player p, string path, ref byte[] temp, long seconds) { protected override bool UndoEntry(Player p, string path, ref byte[] temp, long seconds) {
List<ChunkHeader> list = new List<ChunkHeader>(); List<ChunkHeader> list = new List<ChunkHeader>();
DateTime now = DateTime.Now; DateTime now = DateTime.UtcNow;
int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
Player.UndoPos Pos; Player.UndoPos Pos;
bool isPlayer = p != null && p.group.Permission < LevelPermission.Nobody; bool isPlayer = p != null && p.group.Permission < LevelPermission.Nobody;
@ -112,7 +115,7 @@ namespace MCGalaxy.Util {
|| Block.Convert(Pos.type) == Block.lava || Pos.type == Block.grass) { || Block.Convert(Pos.type) == Block.lava || Pos.type == Block.grass) {
Pos.newtype = oldType; Pos.newExtType = oldExtType; Pos.newtype = oldType; Pos.newExtType = oldExtType;
Pos.extType = newExtType; Pos.timePlaced = now; Pos.extType = newExtType; Pos.timeDelta = timeDelta;
lvl.Blockchange(p, Pos.x, Pos.y, Pos.z, Pos.newtype, Pos.newExtType); lvl.Blockchange(p, Pos.x, Pos.y, Pos.z, Pos.newtype, Pos.newExtType);
if (p != null) p.RedoBuffer.Add(Pos); if (p != null) p.RedoBuffer.Add(Pos);
} }
@ -124,7 +127,7 @@ namespace MCGalaxy.Util {
protected override bool HighlightEntry(Player p, string path, ref byte[] temp, long seconds) { protected override bool HighlightEntry(Player p, string path, ref byte[] temp, long seconds) {
List<ChunkHeader> list = new List<ChunkHeader>(); List<ChunkHeader> list = new List<ChunkHeader>();
DateTime now = DateTime.Now; DateTime now = DateTime.UtcNow;
using (Stream fs = File.OpenRead(path)) using (Stream fs = File.OpenRead(path))
using (BinaryReader r = new BinaryReader(fs)) using (BinaryReader r = new BinaryReader(fs))
@ -170,7 +173,7 @@ namespace MCGalaxy.Util {
static bool CheckChunk(ChunkHeader chunk, DateTime now, long seconds, Player p, out Level lvl) { static bool CheckChunk(ChunkHeader chunk, DateTime now, long seconds, Player p, out Level lvl) {
DateTime time = chunk.BaseTime; DateTime time = chunk.BaseTime;
lvl = null; lvl = null;
if (time.AddSeconds(65536).AddSeconds(seconds) < now) if (time.AddSeconds(65536 + seconds) < now)
return false; // we can safely discard the entire chunk return false; // we can safely discard the entire chunk
lvl = LevelInfo.FindExact(chunk.LevelName); lvl = LevelInfo.FindExact(chunk.LevelName);
@ -199,7 +202,7 @@ namespace MCGalaxy.Util {
byte[] mapNameData = r.ReadBytes(r.ReadUInt16()); byte[] mapNameData = r.ReadBytes(r.ReadUInt16());
header.LevelName = Encoding.UTF8.GetString(mapNameData); header.LevelName = Encoding.UTF8.GetString(mapNameData);
header.BaseTime = new DateTime(r.ReadInt64(), DateTimeKind.Local); header.BaseTime = new DateTime(r.ReadInt64(), DateTimeKind.Local).ToUniversalTime();
header.Entries = r.ReadUInt16(); header.Entries = r.ReadUInt16();
header.DataPosition = s.Position; header.DataPosition = s.Position;
return header; return header;
@ -214,15 +217,16 @@ namespace MCGalaxy.Util {
} }
static ChunkHeader WriteEmptyChunk(BinaryWriter w, Player.UndoPos uP, ref long entriesPos) { static ChunkHeader WriteEmptyChunk(BinaryWriter w, Player.UndoPos uP, ref long entriesPos) {
DateTime time = Server.StartTime.AddSeconds(uP.timeDelta);
byte[] mapBytes = Encoding.UTF8.GetBytes(uP.mapName); byte[] mapBytes = Encoding.UTF8.GetBytes(uP.mapName);
w.Write((ushort)mapBytes.Length); w.Write((ushort)mapBytes.Length);
w.Write(mapBytes); w.Write(mapBytes);
w.Write(uP.timePlaced.ToLocalTime().Ticks); w.Write(time.ToLocalTime().Ticks);
entriesPos = w.BaseStream.Position; entriesPos = w.BaseStream.Position;
w.Write((ushort)0); w.Write((ushort)0);
ChunkHeader header = default(ChunkHeader); ChunkHeader header = default(ChunkHeader);
header.LevelName = uP.mapName; header.BaseTime = uP.timePlaced; header.LevelName = uP.mapName; header.BaseTime = time;
return header; return header;
} }
} }

View File

@ -30,9 +30,10 @@ namespace MCGalaxy.Util {
protected override void SaveUndoData(List<Player.UndoPos> buffer, string path) { protected override void SaveUndoData(List<Player.UndoPos> buffer, string path) {
using (StreamWriter w = File.CreateText(path)) { using (StreamWriter w = File.CreateText(path)) {
foreach (Player.UndoPos uP in buffer) { foreach (Player.UndoPos uP in buffer) {
DateTime time = Server.StartTimeLocal.AddSeconds(uP.timeDelta);
w.Write( w.Write(
uP.mapName + " " + uP.x + " " + uP.y + " " + uP.z + " " + uP.mapName + " " + uP.x + " " + uP.y + " " + uP.z + " " +
uP.timePlaced.ToString(CultureInfo.InvariantCulture).Replace(' ', '&') + " " + time.ToString(CultureInfo.InvariantCulture).Replace(' ', '&') + " " +
uP.type + " " + uP.newtype + " "); uP.type + " " + uP.newtype + " ");
} }
} }
@ -54,7 +55,8 @@ namespace MCGalaxy.Util {
Pos.z = ushort.Parse(lines[i + 3]); Pos.z = ushort.Parse(lines[i + 3]);
string time = lines[i + 4].Replace('&', ' '); string time = lines[i + 4].Replace('&', ' ');
Pos.timePlaced = DateTime.Parse(time, CultureInfo.InvariantCulture); DateTime rawTime = DateTime.Parse(time, CultureInfo.InvariantCulture);
Pos.timeDelta = (int)rawTime.Subtract(Server.StartTimeLocal).TotalSeconds;
Pos.type = byte.Parse(lines[i + 5]); Pos.type = byte.Parse(lines[i + 5]);
Pos.newtype = byte.Parse(lines[i + 6]); Pos.newtype = byte.Parse(lines[i + 6]);
buffer.Add(Pos); buffer.Add(Pos);
@ -63,6 +65,7 @@ namespace MCGalaxy.Util {
protected override bool UndoEntry(Player p, string path, ref byte[] temp, long seconds) { protected override bool UndoEntry(Player p, string path, ref byte[] temp, long seconds) {
Player.UndoPos Pos; Player.UndoPos Pos;
int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
Pos.extType = 0; Pos.newExtType = 0; Pos.extType = 0; Pos.newExtType = 0;
string[] lines = File.ReadAllText(path).Split(' '); string[] lines = File.ReadAllText(path).Split(' ');
@ -84,7 +87,7 @@ namespace MCGalaxy.Util {
Block.Convert(Pos.type) == Block.lava || Pos.type == Block.grass) { Block.Convert(Pos.type) == Block.lava || Pos.type == Block.grass) {
Pos.newtype = Convert.ToByte(lines[(i * 7) - 2]); Pos.newtype = Convert.ToByte(lines[(i * 7) - 2]);
Pos.timePlaced = DateTime.Now; Pos.timeDelta = timeDelta;
foundLevel.Blockchange(p, Pos.x, Pos.y, Pos.z, Pos.newtype, 0); foundLevel.Blockchange(p, Pos.x, Pos.y, Pos.z, Pos.newtype, 0);
if (p != null) p.RedoBuffer.Add(Pos); if (p != null) p.RedoBuffer.Add(Pos);

View File

@ -71,6 +71,7 @@ namespace MCGalaxy
//public static List<MySql.Data.MySqlClient.MySqlCommand> mySQLCommands = new List<MySql.Data.MySqlClient.MySqlCommand>(); //public static List<MySql.Data.MySqlClient.MySqlCommand> mySQLCommands = new List<MySql.Data.MySqlClient.MySqlCommand>();
public static WebServer APIServer; public static WebServer APIServer;
public static WebServer InfoServer; public static WebServer InfoServer;
public static DateTime StartTime, StartTimeLocal;
public static int speedPhysics = 250; public static int speedPhysics = 250;
@ -407,6 +408,8 @@ namespace MCGalaxy
} }
public void Start() { public void Start() {
StartTime = DateTime.UtcNow;
StartTimeLocal = StartTime.ToLocalTime();
shuttingDown = false; shuttingDown = false;
Log("Starting Server"); Log("Starting Server");
try { try {