diff --git a/Commands/Information/CmdAbout.cs b/Commands/Information/CmdAbout.cs index c2d7f2af9..11d9db028 100644 --- a/Commands/Information/CmdAbout.cs +++ b/Commands/Information/CmdAbout.cs @@ -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) diff --git a/Commands/Moderation/CmdHighlight.cs b/Commands/Moderation/CmdHighlight.cs index 266cb1487..74af538cc 100644 --- a/Commands/Moderation/CmdHighlight.cs +++ b/Commands/Moderation/CmdHighlight.cs @@ -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 { } } diff --git a/Commands/building/CmdFill.cs b/Commands/building/CmdFill.cs index 095d0ba7e..aa54a1db9 100644 --- a/Commands/building/CmdFill.cs +++ b/Commands/building/CmdFill.cs @@ -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 buffer = new List(), origins = new List(); + List buffer = new List(), origins = new List(); 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 buffer, List origins, int depth) { - FillPos pos; - pos.X = x; pos.Y = y; pos.Z = z; + SparseBitSet bits, List buffer, List 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) { diff --git a/Commands/building/CmdRedo.cs b/Commands/building/CmdRedo.cs index d3c3bbc8b..9d08c816d 100644 --- a/Commands/building/CmdRedo.cs +++ b/Commands/building/CmdRedo.cs @@ -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); } diff --git a/Commands/building/CmdUndo.cs b/Commands/building/CmdUndo.cs index 9964b74ab..456f97a86 100644 --- a/Commands/building/CmdUndo.cs +++ b/Commands/building/CmdUndo.cs @@ -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; diff --git a/Drawing/DrawOps/FillDrawOp.cs b/Drawing/DrawOps/FillDrawOp.cs index a1c22217a..9780c21f1 100644 --- a/Drawing/DrawOps/FillDrawOp.cs +++ b/Drawing/DrawOps/FillDrawOp.cs @@ -24,7 +24,7 @@ namespace MCGalaxy { public class FillDrawOp : DrawOp { - public List Positions; + public List 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); } } } diff --git a/Levels/BlockQueue.cs b/Levels/BlockQueue.cs index faeac160d..33f752c33 100644 --- a/Levels/BlockQueue.cs +++ b/Levels/BlockQueue.cs @@ -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); diff --git a/Levels/Level.Blocks.cs b/Levels/Level.Blocks.cs index 8b480f366..d59f38693 100644 --- a/Levels/Level.Blocks.cs +++ b/Levels/Level.Blocks.cs @@ -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"; diff --git a/Levels/Level.cs b/Levels/Level.cs index 6468cd47c..938c343d5 100644 --- a/Levels/Level.cs +++ b/Levels/Level.cs @@ -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 { diff --git a/Player/Player.cs b/Player/Player.cs index f4818af00..c245165c4 100644 --- a/Player/Player.cs +++ b/Player/Player.cs @@ -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 UndoBuffer = new List(); public List RedoBuffer = new List(); @@ -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; diff --git a/Player/Undo/UndoFileBin.cs b/Player/Undo/UndoFileBin.cs index 5a4759b2f..6f49cc9ee 100644 --- a/Player/Undo/UndoFileBin.cs +++ b/Player/Undo/UndoFileBin.cs @@ -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 list = new List(); - 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 list = new List(); - 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; } } diff --git a/Player/Undo/UndoFileText.cs b/Player/Undo/UndoFileText.cs index 322eb0e52..fd4facec4 100644 --- a/Player/Undo/UndoFileText.cs +++ b/Player/Undo/UndoFileText.cs @@ -30,9 +30,10 @@ namespace MCGalaxy.Util { protected override void SaveUndoData(List 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); diff --git a/Server/Server.cs b/Server/Server.cs index 19cd7ae58..596d5fa9f 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -71,6 +71,7 @@ namespace MCGalaxy //public static List mySQLCommands = new List(); 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 {