mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-26 14:54:12 -04:00
Memory optimisations in /fill, also only store delta time for undo positions to further save memory.
This commit is contained in:
parent
af3fe2c76d
commit
87758df1e3
@ -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)
|
||||
|
@ -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 { }
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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";
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user