mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-26 14:54:12 -04:00
Merge branch 'UndoCleanup'
This commit is contained in:
commit
f8e83786c2
@ -16,6 +16,7 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using MCGalaxy.Util;
|
||||
|
||||
@ -52,7 +53,7 @@ namespace MCGalaxy.Commands {
|
||||
Player who = PlayerInfo.Find(name);
|
||||
if (who != null) {
|
||||
FoundUser = true;
|
||||
HighlightOnline(p, seconds, who);
|
||||
PerformHighlight(p, seconds, who.UndoBuffer);
|
||||
}
|
||||
|
||||
UndoFile.HighlightPlayer(p, name.ToLower(), seconds, ref FoundUser);
|
||||
@ -63,25 +64,32 @@ namespace MCGalaxy.Commands {
|
||||
Player.SendMessage(p, "Could not find player specified.");
|
||||
}
|
||||
}
|
||||
|
||||
static void HighlightOnline(Player p, long seconds, Player who) {
|
||||
for (int i = who.UndoBuffer.Count - 1; i >= 0; --i) {
|
||||
try {
|
||||
Player.UndoPos undo = who.UndoBuffer[i];
|
||||
Level foundLevel = LevelInfo.FindExact(undo.mapName);
|
||||
if (foundLevel != p.level) continue;
|
||||
|
||||
static void PerformHighlight(Player p, long seconds, UndoCache cache) {
|
||||
UndoCacheNode node = cache.Tail;
|
||||
if (node == null) return;
|
||||
|
||||
while (node != null) {
|
||||
Level lvl = LevelInfo.FindExact(node.MapName);
|
||||
if (lvl != p.level) continue;
|
||||
List<UndoCacheItem> items = node.Items;
|
||||
|
||||
for (int i = items.Count - 1; i >= 0; i--) {
|
||||
UndoCacheItem item = items[i];
|
||||
ushort x, y, z;
|
||||
node.Unpack(item.Index, out x, out y, out z);
|
||||
DateTime time = node.BaseTime.AddSeconds(item.TimeDelta + seconds);
|
||||
if (time < DateTime.UtcNow) return;
|
||||
|
||||
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 == undo.newtype || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
|
||||
byte b = lvl.GetTile(x, y, z);
|
||||
if (b == item.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(undo.x, undo.y, undo.z, Block.red);
|
||||
p.SendBlockchange(x, y, z, Block.red);
|
||||
else
|
||||
p.SendBlockchange(undo.x, undo.y, undo.z, Block.green);
|
||||
p.SendBlockchange(x, y, z, Block.green);
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
node = node.Prev;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MCGalaxy.Util;
|
||||
|
||||
namespace MCGalaxy.Commands {
|
||||
|
||||
@ -30,21 +32,32 @@ namespace MCGalaxy.Commands {
|
||||
|
||||
public override void Use(Player p, string message) {
|
||||
if (message != "") { Help(p); return; }
|
||||
|
||||
for (int i = p.RedoBuffer.Count - 1; i >= 0; i--) {
|
||||
Player.UndoPos Pos = p.RedoBuffer[i];
|
||||
Level lvl = LevelInfo.FindExact(Pos.mapName);
|
||||
if (lvl == null)
|
||||
continue;
|
||||
|
||||
byte type = lvl.GetTile(Pos.x, Pos.y, Pos.z), extType = 0;
|
||||
if (type == Block.custom_block)
|
||||
extType = lvl.GetExtTile(Pos.x, Pos.y, Pos.z);
|
||||
lvl.Blockchange(p, Pos.x, Pos.y, Pos.z, Pos.type, Pos.extType);
|
||||
}
|
||||
|
||||
PerformRedo(p, p.RedoBuffer);
|
||||
Player.SendMessage(p, "Redo performed.");
|
||||
}
|
||||
|
||||
static void PerformRedo(Player p, UndoCache cache) {
|
||||
UndoCacheNode node = cache.Tail;
|
||||
if (node == null) return;
|
||||
|
||||
while (node != null) {
|
||||
Level lvl = LevelInfo.FindExact(node.MapName);
|
||||
if (lvl == null) continue;
|
||||
List<UndoCacheItem> items = node.Items;
|
||||
|
||||
for (int i = items.Count - 1; i >= 0; i--) {
|
||||
UndoCacheItem item = items[i];
|
||||
ushort x, y, z;
|
||||
node.Unpack(item.Index, out x, out y, out z);
|
||||
|
||||
byte type = lvl.GetTile(x, y, z), extType = 0;
|
||||
if (type == Block.custom_block)
|
||||
extType = lvl.GetExtTile(x, y, z);
|
||||
lvl.Blockchange(p, x, y, z, item.Type, item.ExtType);
|
||||
}
|
||||
node = node.Prev;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
Player.SendMessage(p, "/redo - Redoes the Undo you just performed.");
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Copyright 2011 MCGalaxy
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
@ -16,8 +16,7 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using MCGalaxy.Util;
|
||||
|
||||
namespace MCGalaxy.Commands
|
||||
@ -89,12 +88,7 @@ namespace MCGalaxy.Commands
|
||||
}
|
||||
|
||||
Level saveLevel = null;
|
||||
for (int i = who.UndoBuffer.Count - 1; i >= 0; --i) {
|
||||
try {
|
||||
Player.UndoPos Pos = who.UndoBuffer[i];
|
||||
if (!CheckBlockPlayer(p, seconds, Pos, ref saveLevel)) break;
|
||||
} catch { }
|
||||
}
|
||||
PerformUndo(p, seconds, who.UndoBuffer, ref saveLevel);
|
||||
bool foundUser = false;
|
||||
UndoFile.UndoPlayer(p, whoName.ToLower(), seconds, ref foundUser);
|
||||
|
||||
@ -159,24 +153,41 @@ namespace MCGalaxy.Commands
|
||||
p.level.Save(true);
|
||||
}
|
||||
|
||||
bool CheckBlockPlayer(Player p, long seconds, Player.UndoPos undo, ref Level saveLevel) {
|
||||
Level lvl = LevelInfo.FindExact(undo.mapName);
|
||||
saveLevel = lvl;
|
||||
byte b = lvl.GetTile(undo.x, undo.y, undo.z);
|
||||
DateTime time = Server.StartTime.AddSeconds(undo.timeDelta + seconds);
|
||||
if (time < DateTime.UtcNow) return false;
|
||||
static void PerformUndo(Player p, long seconds, UndoCache cache, ref Level saveLvl) {
|
||||
UndoCacheNode node = cache.Tail;
|
||||
if (node == null) return;
|
||||
|
||||
if (b == undo.newtype || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
|
||||
undo.newtype = undo.type; undo.newExtType = undo.extType;
|
||||
byte extType = 0;
|
||||
if (b == Block.custom_block)
|
||||
extType = lvl.GetExtTile(undo.x, undo.y, undo.z);
|
||||
while (node != null) {
|
||||
Level lvl = LevelInfo.FindExact(node.MapName);
|
||||
if (lvl == null) continue;
|
||||
saveLvl = lvl;
|
||||
List<UndoCacheItem> items = node.Items;
|
||||
|
||||
lvl.Blockchange(p, undo.x, undo.y, undo.z, undo.type, undo.extType);
|
||||
undo.type = b; undo.extType = extType;
|
||||
if (p != null) p.RedoBuffer.Add(undo);
|
||||
for (int i = items.Count - 1; i >= 0; i--) {
|
||||
UndoCacheItem item = items[i];
|
||||
ushort x, y, z;
|
||||
node.Unpack(item.Index, out x, out y, out z);
|
||||
DateTime time = node.BaseTime.AddSeconds(item.TimeDelta + seconds);
|
||||
if (time < DateTime.UtcNow) return;
|
||||
|
||||
byte b = lvl.GetTile(x, y, z);
|
||||
if (b == item.NewType || Block.Convert(b) == Block.water || Block.Convert(b) == Block.lava) {
|
||||
Player.UndoPos uP = default(Player.UndoPos);
|
||||
uP.newtype = item.Type; uP.newExtType = item.ExtType;
|
||||
byte extType = 0;
|
||||
if (b == Block.custom_block) extType = lvl.GetExtTile(x, y, z);
|
||||
lvl.Blockchange(p, x, y, z, item.Type, item.ExtType);
|
||||
|
||||
uP.type = b; uP.extType = extType;
|
||||
uP.x = x; uP.y = y; uP.z = z;
|
||||
uP.mapName = node.MapName;
|
||||
time = node.BaseTime.AddSeconds(item.TimeDelta);
|
||||
uP.timeDelta = (int)time.Subtract(Server.StartTime).TotalSeconds;
|
||||
if (p != null) p.RedoBuffer.Add(lvl, uP);
|
||||
}
|
||||
}
|
||||
node = node.Prev;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckBlockPhysics(Player p, long seconds, int i, Level.UndoPos undo) {
|
||||
|
@ -160,7 +160,7 @@ namespace MCGalaxy {
|
||||
Pos.type = oldType; Pos.extType = oldExtType;
|
||||
Pos.newtype = type; Pos.newExtType = extType;
|
||||
Pos.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
|
||||
p.UndoBuffer.Add(Pos);
|
||||
p.UndoBuffer.Add(this, Pos);
|
||||
}
|
||||
|
||||
bool CheckTNTWarsChange(Player p, ushort x, ushort y, ushort z, ref byte type) {
|
||||
@ -328,7 +328,7 @@ namespace MCGalaxy {
|
||||
Pos.type = b; Pos.extType = extB;
|
||||
Pos.newtype = type; Pos.newExtType = extType;
|
||||
Pos.timeDelta = (int)DateTime.UtcNow.Subtract(Server.StartTime).TotalSeconds;
|
||||
p.UndoBuffer.Add(Pos);
|
||||
p.UndoBuffer.Add(this, Pos);
|
||||
|
||||
errorLocation = "Setting tile";
|
||||
p.loginBlocks++;
|
||||
|
@ -443,6 +443,7 @@
|
||||
<Compile Include="Player\Group\GroupProperties.cs" />
|
||||
<Compile Include="Player\Player.Handlers.cs" />
|
||||
<Compile Include="Player\PlayerInfo.cs" />
|
||||
<Compile Include="Player\Undo\UndoCache.cs" />
|
||||
<Compile Include="Player\Waypoint.cs" />
|
||||
<Compile Include="Player\Player.Timers.cs" />
|
||||
<Compile Include="Player\Undo\UndoFile.cs" />
|
||||
|
@ -235,8 +235,8 @@ namespace MCGalaxy {
|
||||
|
||||
//Undo
|
||||
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>();
|
||||
public UndoCache UndoBuffer = new UndoCache();
|
||||
public UndoCache RedoBuffer = new UndoCache();
|
||||
|
||||
|
||||
public bool showPortals = false;
|
||||
|
111
Player/Undo/UndoCache.cs
Normal file
111
Player/Undo/UndoCache.cs
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright 2015 MCGalaxy
|
||||
|
||||
Dual-licensed under the Educational Community License, Version 2.0 and
|
||||
the GNU General Public License, Version 3 (the "Licenses"); you may
|
||||
not use this file except in compliance with the Licenses. You may
|
||||
obtain a copy of the Licenses at
|
||||
|
||||
http://www.opensource.org/licenses/ecl2.php
|
||||
http://www.gnu.org/licenses/gpl-3.0.html
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the Licenses are distributed on an "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
||||
or implied. See the Licenses for the specific language governing
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace MCGalaxy.Util {
|
||||
|
||||
public sealed class UndoCache {
|
||||
|
||||
/// <summary> The oldest/first node in the cache. </summary>
|
||||
public UndoCacheNode Head;
|
||||
|
||||
/// <summary> The newest/last node in the cache. </summary>
|
||||
public UndoCacheNode Tail;
|
||||
|
||||
/// <summary> Total number of items in the cache. </summary>
|
||||
public volatile int Count;
|
||||
|
||||
/// <summary> Appends an item to the cache. </summary>
|
||||
public void Add(Level lvl, Player.UndoPos item) {
|
||||
DateTime time = Server.StartTime.AddSeconds(item.timeDelta);
|
||||
if (Head == null) {
|
||||
Head = UndoCacheNode.Make(lvl, time);
|
||||
Tail = Head;
|
||||
}
|
||||
|
||||
if (lvl.name != Tail.MapName || lvl.Width != Tail.Width || lvl.Height != Tail.Height ||
|
||||
lvl.Length != Tail.Length || Math.Abs((time - Tail.BaseTime).TotalSeconds) > 32767) {
|
||||
UndoCacheNode node = UndoCacheNode.Make(lvl, time);
|
||||
Tail.Next = node; node.Prev = Tail;
|
||||
Tail = node;
|
||||
}
|
||||
|
||||
short timeDiff = (short)(time - Tail.BaseTime).TotalSeconds;
|
||||
Tail.Items.Add(UndoCacheItem.Make(Tail, timeDiff, ref item));
|
||||
Count++;
|
||||
}
|
||||
|
||||
/// <summary> Removes all items from the cache and resets the state to default. </summary>
|
||||
public void Clear() {
|
||||
Count = 0;
|
||||
if( Head == null ) return;
|
||||
|
||||
UndoCacheNode node = Head;
|
||||
while( node != null ) {
|
||||
node.Items.Clear();
|
||||
node = node.Next;
|
||||
}
|
||||
Head = null; Tail = null;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UndoCacheNode {
|
||||
|
||||
public string MapName;
|
||||
public int Width, Height, Length;
|
||||
public DateTime BaseTime;
|
||||
|
||||
public UndoCacheNode Prev, Next;
|
||||
public List<UndoCacheItem> Items = new List<UndoCacheItem>();
|
||||
|
||||
public static UndoCacheNode Make(Level lvl, DateTime time) {
|
||||
UndoCacheNode node = new UndoCacheNode();
|
||||
node.MapName = lvl.name;
|
||||
node.Width = lvl.Width; node.Height = lvl.Height; node.Length = lvl.Length;
|
||||
node.BaseTime = time;
|
||||
return node;
|
||||
}
|
||||
|
||||
public void Unpack(int index, out ushort x, out ushort y, out ushort z) {
|
||||
x = (ushort)(index % Width);
|
||||
y = (ushort)(index / (Width * Length));
|
||||
z = (ushort)((index / Width) % Length);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct UndoCacheItem {
|
||||
public int Index;
|
||||
public byte Type, ExtType;
|
||||
public byte NewType, NewExtType;
|
||||
public short TimeDelta;
|
||||
|
||||
public static UndoCacheItem Make(UndoCacheNode node, short timeDelta, ref Player.UndoPos pos) {
|
||||
UndoCacheItem item = default(UndoCacheItem);
|
||||
item.Index = pos.x + node.Width * (pos.z + node.Length * pos.y);
|
||||
item.Type = pos.type; item.ExtType = pos.extType;
|
||||
item.NewType = pos.newtype; item.NewExtType = pos.newExtType;
|
||||
item.TimeDelta = timeDelta;
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
@ -30,6 +30,8 @@ namespace MCGalaxy.Util {
|
||||
|
||||
protected abstract void SaveUndoData(List<Player.UndoPos> buffer, string path);
|
||||
|
||||
protected abstract void SaveUndoData(UndoCache buffer, string path);
|
||||
|
||||
protected abstract void ReadUndoData(List<Player.UndoPos> buffer, string path);
|
||||
|
||||
protected abstract bool UndoEntry(Player p, string path, ref byte[] temp, long seconds);
|
||||
@ -39,7 +41,7 @@ namespace MCGalaxy.Util {
|
||||
protected abstract string Extension { get; }
|
||||
|
||||
public static void SaveUndo(Player p) {
|
||||
if( p == null || p.UndoBuffer == null || p.UndoBuffer.Count < 1) return;
|
||||
if( p == null || p.UndoBuffer.Count < 1) return;
|
||||
|
||||
CreateDefaultDirectories();
|
||||
if (Directory.GetDirectories(undoDir).Length >= Server.totalUndo) {
|
||||
@ -54,7 +56,7 @@ namespace MCGalaxy.Util {
|
||||
|
||||
int numFiles = Directory.GetFiles(playerDir).Length;
|
||||
string path = Path.Combine(playerDir, numFiles + NewFormat.Extension);
|
||||
NewFormat.SaveUndoData(p.UndoBuffer.ToList(), path);
|
||||
NewFormat.SaveUndoData(p.UndoBuffer, path);
|
||||
}
|
||||
|
||||
public static void UndoPlayer(Player p, string targetName, long seconds, ref bool FoundUser) {
|
||||
@ -96,11 +98,11 @@ namespace MCGalaxy.Util {
|
||||
}
|
||||
|
||||
static int CompareFiles(string a, string b) {
|
||||
int aNumStart = a.LastIndexOf('\\'), bNumStart = b.LastIndexOf('\\');
|
||||
int aNumStart = a.LastIndexOf('\\'), bNumStart = b.LastIndexOf('\\');
|
||||
int aNumEnd = a.LastIndexOf('.'), bNumEnd = b.LastIndexOf('.');
|
||||
if (aNumStart < 0 || bNumStart < 0 || aNumEnd < 0 ||
|
||||
bNumEnd < 0 || aNumStart >= aNumEnd || bNumStart >= bNumEnd)
|
||||
return a.CompareTo(b);
|
||||
return a.CompareTo(b);
|
||||
|
||||
int aNum, bNum;
|
||||
if (!int.TryParse(a.Substring(aNumStart + 1, aNumEnd - aNumStart - 1), out aNum) ||
|
||||
|
@ -32,24 +32,57 @@ namespace MCGalaxy.Util {
|
||||
using (FileStream fs = File.Create(path)) {
|
||||
BinaryWriter w = new BinaryWriter(fs);
|
||||
long entriesPos = 0;
|
||||
ChunkHeader lastChunk = default(ChunkHeader);
|
||||
ChunkHeader last = default(ChunkHeader);
|
||||
|
||||
foreach (Player.UndoPos uP in buffer) {
|
||||
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);
|
||||
int timeDiff = (int)(time - last.BaseTime).TotalSeconds;
|
||||
if (last.LevelName != uP.mapName || timeDiff > 65535 || last.Entries == ushort.MaxValue) {
|
||||
WriteChunkEntries(w, last.Entries, entriesPos);
|
||||
last = WriteEmptyChunk(w, uP.mapName, time, ref entriesPos);
|
||||
}
|
||||
|
||||
w.Write((ushort)timeDiff);
|
||||
w.Write(uP.x); w.Write(uP.y); w.Write(uP.z);
|
||||
w.Write(uP.type); w.Write(uP.extType);
|
||||
w.Write(uP.newtype); w.Write(uP.newExtType);
|
||||
lastChunk.Entries++;
|
||||
last.Entries++;
|
||||
}
|
||||
if (last.Entries > 0)
|
||||
WriteChunkEntries(w, last.Entries, entriesPos);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SaveUndoData(UndoCache buffer, string path) {
|
||||
using (FileStream fs = File.Create(path)) {
|
||||
BinaryWriter w = new BinaryWriter(fs);
|
||||
long entriesPos = 0;
|
||||
ChunkHeader last = default(ChunkHeader);
|
||||
UndoCacheNode node = buffer.Tail;
|
||||
|
||||
while (node != null) {
|
||||
List<UndoCacheItem> items = node.Items;
|
||||
for (int i = 0; i < items.Count; i++) {
|
||||
UndoCacheItem uP = items[i];
|
||||
DateTime time = node.BaseTime.AddSeconds(uP.TimeDelta);
|
||||
int timeDiff = (int)(time - last.BaseTime).TotalSeconds;
|
||||
if (last.LevelName != node.MapName || timeDiff > 65535 || last.Entries == ushort.MaxValue) {
|
||||
WriteChunkEntries(w, last.Entries, entriesPos);
|
||||
last = WriteEmptyChunk(w, node.MapName, time, ref entriesPos);
|
||||
}
|
||||
ushort x, y, z;
|
||||
node.Unpack(uP.Index, out x, out y, out z);
|
||||
|
||||
w.Write((ushort)timeDiff);
|
||||
w.Write(x); w.Write(y); w.Write(z);
|
||||
w.Write(uP.Type); w.Write(uP.ExtType);
|
||||
w.Write(uP.NewType); w.Write(uP.NewExtType);
|
||||
last.Entries++;
|
||||
}
|
||||
if (last.Entries > 0)
|
||||
WriteChunkEntries(w, last.Entries, entriesPos);
|
||||
node = node.Prev;
|
||||
}
|
||||
if (lastChunk.Entries > 0)
|
||||
WriteChunkEntries(w, lastChunk.Entries, entriesPos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,8 +135,8 @@ namespace MCGalaxy.Util {
|
||||
fs.Read(temp, 0, chunk.Entries * entrySize);
|
||||
|
||||
for (int j = chunk.Entries - 1; j >= 0; j-- ) {
|
||||
int offset = j * entrySize;
|
||||
DateTime time = chunk.BaseTime.AddSeconds(U16(temp, offset + 0));
|
||||
int offset = j * entrySize;
|
||||
DateTime time = chunk.BaseTime.AddSeconds(U16(temp, offset + 0));
|
||||
if (time.AddSeconds(seconds) < now) return false;
|
||||
Pos.x = U16(temp, offset + 2); Pos.y = U16(temp, offset + 4); Pos.z = U16(temp, offset + 6);
|
||||
|
||||
@ -117,7 +150,7 @@ namespace MCGalaxy.Util {
|
||||
Pos.newtype = oldType; Pos.newExtType = oldExtType;
|
||||
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);
|
||||
if (p != null) p.RedoBuffer.Add(lvl, Pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -145,8 +178,8 @@ namespace MCGalaxy.Util {
|
||||
fs.Read(temp, 0, chunk.Entries * entrySize);
|
||||
|
||||
for (int j = chunk.Entries - 1; j >= 0; j-- ) {
|
||||
int offset = j * entrySize;
|
||||
DateTime time = chunk.BaseTime.AddSeconds(U16(temp, offset + 0));
|
||||
int offset = j * entrySize;
|
||||
DateTime time = chunk.BaseTime.AddSeconds(U16(temp, offset + 0));
|
||||
if (time.AddSeconds(seconds) < now) return false;
|
||||
ushort x = U16(temp, offset + 2), y = U16(temp, offset + 4), z = U16(temp, offset + 6);
|
||||
|
||||
@ -167,7 +200,7 @@ namespace MCGalaxy.Util {
|
||||
}
|
||||
|
||||
static ushort U16(byte[] buffer, int offset) {
|
||||
return (ushort)(buffer[offset + 0] | buffer[offset + 1] << 8);
|
||||
return (ushort)(buffer[offset + 0] | buffer[offset + 1] << 8);
|
||||
}
|
||||
|
||||
static bool CheckChunk(ChunkHeader chunk, DateTime now, long seconds, Player p, out Level lvl) {
|
||||
@ -216,9 +249,8 @@ namespace MCGalaxy.Util {
|
||||
w.BaseStream.Seek(curPos, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
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);
|
||||
static ChunkHeader WriteEmptyChunk(BinaryWriter w, string mapName, DateTime time, ref long entriesPos) {
|
||||
byte[] mapBytes = Encoding.UTF8.GetBytes(mapName);
|
||||
w.Write((ushort)mapBytes.Length);
|
||||
w.Write(mapBytes);
|
||||
w.Write(time.ToLocalTime().Ticks);
|
||||
@ -226,7 +258,7 @@ namespace MCGalaxy.Util {
|
||||
entriesPos = w.BaseStream.Position;
|
||||
w.Write((ushort)0);
|
||||
ChunkHeader header = default(ChunkHeader);
|
||||
header.LevelName = uP.mapName; header.BaseTime = time;
|
||||
header.LevelName = mapName; header.BaseTime = time;
|
||||
return header;
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ 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);
|
||||
DateTime time = Server.StartTimeLocal.AddSeconds(uP.timeDelta);
|
||||
w.Write(
|
||||
uP.mapName + " " + uP.x + " " + uP.y + " " + uP.z + " " +
|
||||
time.ToString(CultureInfo.InvariantCulture).Replace(' ', '&') + " " +
|
||||
@ -39,6 +39,10 @@ namespace MCGalaxy.Util {
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SaveUndoData(UndoCache buffer, string path) {
|
||||
throw new NotImplementedException("The .txt based undo files are deprecated.");
|
||||
}
|
||||
|
||||
protected override void ReadUndoData(List<Player.UndoPos> buffer, string path) {
|
||||
Player.UndoPos Pos;
|
||||
Pos.extType = 0; Pos.newExtType = 0;
|
||||
@ -74,14 +78,14 @@ namespace MCGalaxy.Util {
|
||||
try {
|
||||
// line format: mapName x y z date oldblock newblock
|
||||
if (!InTime(lines[(i * 7) - 3], seconds)) return false;
|
||||
Level foundLevel = LevelInfo.FindExact(lines[(i * 7) - 7]);
|
||||
if (foundLevel == null) continue;
|
||||
Level lvl = LevelInfo.FindExact(lines[(i * 7) - 7]);
|
||||
if (lvl == null) continue;
|
||||
|
||||
Pos.mapName = foundLevel.name;
|
||||
Pos.mapName = lvl.name;
|
||||
Pos.x = Convert.ToUInt16(lines[(i * 7) - 6]);
|
||||
Pos.y = Convert.ToUInt16(lines[(i * 7) - 5]);
|
||||
Pos.z = Convert.ToUInt16(lines[(i * 7) - 4]);
|
||||
Pos.type = foundLevel.GetTile(Pos.x, Pos.y, Pos.z);
|
||||
Pos.type = lvl.GetTile(Pos.x, Pos.y, Pos.z);
|
||||
|
||||
if (Pos.type == Convert.ToByte(lines[(i * 7) - 1]) || Block.Convert(Pos.type) == Block.water ||
|
||||
Block.Convert(Pos.type) == Block.lava || Pos.type == Block.grass) {
|
||||
@ -89,8 +93,8 @@ namespace MCGalaxy.Util {
|
||||
Pos.newtype = Convert.ToByte(lines[(i * 7) - 2]);
|
||||
Pos.timeDelta = timeDelta;
|
||||
|
||||
foundLevel.Blockchange(p, Pos.x, Pos.y, Pos.z, Pos.newtype, 0);
|
||||
if (p != null) p.RedoBuffer.Add(Pos);
|
||||
lvl.Blockchange(p, Pos.x, Pos.y, Pos.z, Pos.newtype, 0);
|
||||
if (p != null) p.RedoBuffer.Add(lvl, Pos);
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user