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;
Deleted = inCache[i].deleted;
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);
if (!Deleted)

View File

@ -67,19 +67,19 @@ namespace MCGalaxy.Commands {
static void HighlightOnline(Player p, long seconds, Player who) {
for (int i = who.UndoBuffer.Count - 1; i >= 0; --i) {
try {
Player.UndoPos Pos = who.UndoBuffer[i];
Level foundLevel = LevelInfo.FindExact(Pos.mapName);
Player.UndoPos undo = who.UndoBuffer[i];
Level foundLevel = LevelInfo.FindExact(undo.mapName);
if (foundLevel != p.level) continue;
byte b = foundLevel.GetTile(Pos.x, Pos.y, Pos.z);
if (Pos.timePlaced.AddSeconds(seconds) < DateTime.Now)
break;
byte b = foundLevel.GetTile(undo.x, undo.y, undo.z);
DateTime time = Server.StartTime.AddSeconds(undo.timeDelta + seconds);
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)
p.SendBlockchange(Pos.x, Pos.y, Pos.z, Block.red);
p.SendBlockchange(undo.x, undo.y, undo.z, Block.red);
else
p.SendBlockchange(Pos.x, Pos.y, Pos.z, Block.green);
p.SendBlockchange(undo.x, undo.y, undo.z, Block.green);
}
} 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; }
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);
int totalFill = origins.Count;
for (int i = 0; i < totalFill; i++) {
FillPos pos = origins[i];
FloodFill(p, pos.X, pos.Y, pos.Z, oldType, oldExtType, cpos.solid, bits, buffer, origins, 0);
int pos = origins[i];
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;
}
@ -91,14 +92,12 @@ namespace MCGalaxy.Commands {
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,
SparseBitSet bits, List<FillPos> buffer, List<FillPos> origins, int depth) {
FillPos pos;
pos.X = x; pos.Y = y; pos.Z = z;
SparseBitSet bits, List<int> buffer, List<int> origins, int depth) {
if (bits.Get(x, y, z)) return;
if (depth > 2000) { origins.Add(pos); return; }
int index = p.level.PosToInt(x, y, z);
if (depth > 2000) { origins.Add(index); return; }
bits.Set(x, y, z, true);
buffer.Add(pos);
buffer.Add(index);
if (fillType != SolidType.verticalX) { // x
if (CheckTile(p, (ushort)(x + 1), y, z, oldType, oldExtType))
@ -131,9 +130,8 @@ namespace MCGalaxy.Commands {
if (tile == oldTile && tile == Block.custom_block) {
byte extTile = p.level.GetExtTile(x, y, z);
return extTile == oldExtTile;
} else {
return tile == oldTile;
}
return tile == oldTile;
}
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);
Pos.newtype = Pos.type; Pos.newExtType = Pos.extType;
Pos.type = type; Pos.extType = extType;
Pos.timePlaced = DateTime.Now;
Pos.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
p.UndoBuffer.Add(Pos);
}

View File

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

View File

@ -24,7 +24,7 @@ namespace MCGalaxy {
public class FillDrawOp : DrawOp {
public List<FillPos> Positions;
public List<int> Positions;
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,
ushort y2, ushort z2, Player p, Level lvl, Brush brush) {
foreach (FillPos pos in Positions) {
PlaceBlock(p, lvl, pos.X, pos.Y, pos.Z, brush);
ushort x, y, z;
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++) {
block item = l.blockqueue[c];
bP.name = item.p.name;
bP.TimePerformed = DateTime.Now;
bP.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
ushort x, y, z;
l.IntToPos(item.index, out x, out y, out z);

View File

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

View File

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

View File

@ -238,7 +238,7 @@ namespace MCGalaxy {
}
//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> RedoBuffer = new List<UndoPos>();
@ -1000,7 +1000,7 @@ namespace MCGalaxy {
Level.BlockPos bP;
bP.name = name;
bP.TimePerformed = DateTime.Now;
bP.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
bP.index = level.PosToInt(x, y, z);
bP.type = type;
bP.extType = extType;

View File

@ -35,7 +35,8 @@ namespace MCGalaxy.Util {
ChunkHeader lastChunk = default(ChunkHeader);
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) {
WriteChunkEntries(w, lastChunk.Entries, entriesPos);
lastChunk = WriteEmptyChunk(w, uP, ref entriesPos);
@ -66,7 +67,8 @@ namespace MCGalaxy.Util {
Pos.mapName = chunk.LevelName;
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.type = r.ReadByte(); Pos.extType = 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) {
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;
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) {
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);
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) {
List<ChunkHeader> list = new List<ChunkHeader>();
DateTime now = DateTime.Now;
DateTime now = DateTime.UtcNow;
using (Stream fs = File.OpenRead(path))
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) {
DateTime time = chunk.BaseTime;
lvl = null;
if (time.AddSeconds(65536).AddSeconds(seconds) < now)
if (time.AddSeconds(65536 + seconds) < now)
return false; // we can safely discard the entire chunk
lvl = LevelInfo.FindExact(chunk.LevelName);
@ -199,7 +202,7 @@ namespace MCGalaxy.Util {
byte[] mapNameData = r.ReadBytes(r.ReadUInt16());
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.DataPosition = s.Position;
return header;
@ -214,15 +217,16 @@ namespace MCGalaxy.Util {
}
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);
w.Write((ushort)mapBytes.Length);
w.Write(mapBytes);
w.Write(uP.timePlaced.ToLocalTime().Ticks);
w.Write(time.ToLocalTime().Ticks);
entriesPos = w.BaseStream.Position;
w.Write((ushort)0);
ChunkHeader header = default(ChunkHeader);
header.LevelName = uP.mapName; header.BaseTime = uP.timePlaced;
header.LevelName = uP.mapName; header.BaseTime = time;
return header;
}
}

View File

@ -30,9 +30,10 @@ namespace MCGalaxy.Util {
protected override void SaveUndoData(List<Player.UndoPos> buffer, string path) {
using (StreamWriter w = File.CreateText(path)) {
foreach (Player.UndoPos uP in buffer) {
DateTime time = Server.StartTimeLocal.AddSeconds(uP.timeDelta);
w.Write(
uP.mapName + " " + uP.x + " " + uP.y + " " + uP.z + " " +
uP.timePlaced.ToString(CultureInfo.InvariantCulture).Replace(' ', '&') + " " +
time.ToString(CultureInfo.InvariantCulture).Replace(' ', '&') + " " +
uP.type + " " + uP.newtype + " ");
}
}
@ -54,7 +55,8 @@ namespace MCGalaxy.Util {
Pos.z = ushort.Parse(lines[i + 3]);
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.newtype = byte.Parse(lines[i + 6]);
buffer.Add(Pos);
@ -63,6 +65,7 @@ namespace MCGalaxy.Util {
protected override bool UndoEntry(Player p, string path, ref byte[] temp, long seconds) {
Player.UndoPos Pos;
int timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
Pos.extType = 0; Pos.newExtType = 0;
string[] lines = File.ReadAllText(path).Split(' ');
@ -84,7 +87,7 @@ namespace MCGalaxy.Util {
Block.Convert(Pos.type) == Block.lava || Pos.type == Block.grass) {
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);
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 WebServer APIServer;
public static WebServer InfoServer;
public static DateTime StartTime, StartTimeLocal;
public static int speedPhysics = 250;
@ -407,6 +408,8 @@ namespace MCGalaxy
}
public void Start() {
StartTime = DateTime.UtcNow;
StartTimeLocal = StartTime.ToLocalTime();
shuttingDown = false;
Log("Starting Server");
try {