DB: /highlight now uses new BlockDB

This commit is contained in:
UnknownShadow200 2017-01-02 10:05:50 +11:00
parent 831f002d34
commit 8d2c184589
4 changed files with 87 additions and 67 deletions

View File

@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using MCGalaxy.DB;
using MCGalaxy.Undo;
namespace MCGalaxy.Commands {
@ -33,7 +34,6 @@ namespace MCGalaxy.Commands {
public override void Use(Player p, string message) {
TimeSpan delta;
bool found = false;
if (Player.IsSuper(p)) { MessageInGameOnly(p); return; }
if (message == "") message = p.name + " 1800";
string[] args = message.Split(' ');
@ -46,28 +46,31 @@ namespace MCGalaxy.Commands {
delta = TimeSpan.FromMinutes(30);
}
string name = PlayerInfo.FindMatchesPreferOnline(p, args[0]);
if (name == null) return;
DateTime start = DateTime.UtcNow.Subtract(delta);
Player who = PlayerInfo.Find(args[0]);
bool done = false;
if (who != null) {
found = true;
UndoCache cache = who.UndoBuffer;
using (IDisposable locker = cache.ClearLock.AccquireReadLock()) {
done = HighlightBlocks(p, start, cache);
}
int[] ids = NameConverter.FindIds(name);
bool found = false, done = false;
if (ids.Length > 0) {
HighlightHelper helper = new HighlightHelper();
done = helper.DoHighlight(ids, start, p);
found = helper.found;
}
if (!done) {
UndoFormatArgs undoArgs = new UndoFormatArgs(p, start, DateTime.MaxValue, null);
UndoFormat.DoHighlight(args[0].ToLower(), ref found, undoArgs);
UndoFormat.DoHighlight(name.ToLower(), ref found, undoArgs);
}
if (found) {
Player.Message(p, "Now highlighting past &b{0} %Sfor {1}",
delta.Shorten(), PlayerInfo.GetColoredName(p, args[0]));
delta.Shorten(), PlayerInfo.GetColoredName(p, name));
Player.Message(p, "&cUse /reload to un-highlight");
} else {
Player.Message(p, "Could not find player specified.");
Player.Message(p, "No changes found by {1} %Sin the past &b{0}",
delta.Shorten(), PlayerInfo.GetColoredName(p, name));
}
}
@ -79,11 +82,43 @@ namespace MCGalaxy.Commands {
}
}
static bool HighlightBlocks(Player p, DateTime start, UndoCache cache) {
UndoFormatArgs args = new UndoFormatArgs(p, start, DateTime.MaxValue, null);
UndoFormat format = new UndoFormatOnline(cache);
UndoFormat.DoHighlight(null, format, args);
return args.Stop;
class HighlightHelper {
Player p;
BufferedBlockSender buffer;
Vec3U16 dims;
public bool found;
public bool DoHighlight(int[] ids, DateTime start, Player p) {
buffer = new BufferedBlockSender(p);
this.p = p;
bool reachedStart = p.level.BlockDB.FindChangesBy(ids, start, DateTime.MaxValue,
out dims, HighlightBlock);
buffer.Send(true);
buffer.player = null;
buffer.level = null;
buffer = null;
this.p = null;
return reachedStart;
}
void HighlightBlock(BlockDBEntry entry) {
byte oldBlock = entry.OldRaw, newBlock = entry.NewRaw;
if ((entry.Flags & BlockDBFlags.OldCustom) != 0) oldBlock = Block.custom_block;
if ((entry.Flags & BlockDBFlags.NewCustom) != 0) newBlock = Block.custom_block;
found = true;
byte highlight = (newBlock == Block.air
|| Block.Convert(oldBlock) == Block.water || oldBlock == Block.waterstill
|| Block.Convert(oldBlock) == Block.lava || oldBlock == Block.lavastill)
? Block.red : Block.green;
int x = entry.Index % dims.X;
int y = (entry.Index / dims.X) / dims.Z;
int z = (entry.Index / dims.X) % dims.Z;
int index = p.level.PosToInt((ushort)x, (ushort)y, (ushort)z);
buffer.Add(index, highlight, 0);
}
}
public override void Help(Player p) {

View File

@ -112,11 +112,9 @@ namespace MCGalaxy.DB {
Vec3U16 dims = Dims;
// Read entries from memory cache
int index = (y * dims.Z + z) * dims.X + x;
FastList<BlockDBEntry> entries = Cache;
for (int i = 0; i < entries.Count; i++) {
if (entries.Items[i].Index != index) continue;
output(entries.Items[i]);
for (int i = 0; i < Cache.Count; i++) {
if (Cache.Items[i].Index != index) continue;
output(Cache.Items[i]);
}
// Read entries from disc cache
@ -132,22 +130,31 @@ namespace MCGalaxy.DB {
}
/// <summary> Outputs all block changes by the given players. </summary>
public void FindChangesBy(int[] ids, DateTime start, DateTime end,
/// <returns> whether an entry before start time was reached. </returns>
public bool FindChangesBy(int[] ids, DateTime start, DateTime end,
out Vec3U16 dims, Action<BlockDBEntry> output) {
long startDelta = (long)start.Subtract(Epoch).TotalSeconds;
long endDelta = (long)end.Subtract(Epoch).TotalSeconds;
using (IDisposable readLock = locker.AccquireReadLock()) {
dims = Dims;
// Read entries from memory cache
for (int i = Cache.Count - 1; i >= 0; i--) {
BlockDBEntry entry = Cache.Items[i];
if (entry.TimeDelta < startDelta) return true;
if (entry.TimeDelta > endDelta) continue;
for (int j = 0; j < ids.Length; j++) {
if (entry.PlayerID != ids[j]) continue;
output(entry); break;
}
}
if (!File.Exists(FilePath)) return;
int startDelta = (int)start.Subtract(Epoch).TotalSeconds;
int endDelta = (int)end.Subtract(Epoch).TotalSeconds;
// Read entries from disc cache
if (!File.Exists(FilePath)) return false;
using (Stream s = File.OpenRead(FilePath)) {
BlockDBFile.ReadHeader(s, out dims);
if (ids.Length == 1) {
BlockDBFile.FindChangesBy(s, ids[0], startDelta, endDelta, output);
} else {
BlockDBFile.FindChangesBy(s, ids, startDelta, endDelta, output);
}
return BlockDBFile.FindChangesBy(s, ids, startDelta, endDelta, output);
}
}
}

View File

@ -100,7 +100,9 @@ namespace MCGalaxy.DB {
}
/// <summary> Iterates from the very newest to oldest entry in the BlockDB. </summary>
public static void FindChangesBy(Stream s, int id, int start, int end, Action<BlockDBEntry> output) {
/// <returns> whether an entry before start time was reached. </returns>
public static bool FindChangesBy(Stream s, int[] ids, long start, long end,
Action<BlockDBEntry> output) {
byte[] bulk = new byte[BulkEntries * EntrySize];
fixed (byte* ptr = bulk) {
int entries = (int)(s.Length / EntrySize) - HeaderEntries;
@ -109,50 +111,26 @@ namespace MCGalaxy.DB {
while (entries > 0) {
int count = Math.Min(entries, BulkEntries);
s.Position -= count * EntrySize;
ReadFully(s, bulk, count * EntrySize);
BlockDBEntry* entryPtr = (BlockDBEntry*)ptr;
entryPtr += (count - 1);
for (int i = 0; i < count; i++) {
if (entryPtr->TimeDelta < start) return;
if (entryPtr->TimeDelta <= end && entryPtr->PlayerID == id) {
output(*entryPtr);
}
entryPtr++;
}
entries -= count;
}
}
}
/// <summary> Iterates from the very newest to oldest entry in the BlockDB. </summary>
public static void FindChangesBy(Stream s, int[] ids, int start, int end, Action<BlockDBEntry> output) {
byte[] bulk = new byte[BulkEntries * EntrySize];
fixed (byte* ptr = bulk) {
int entries = (int)(s.Length / EntrySize) - HeaderEntries;
s.Position = s.Length;
while (entries > 0) {
int count = Math.Min(entries, BulkEntries);
s.Position -= count * EntrySize;
ReadFully(s, bulk, count * EntrySize);
BlockDBEntry* entryPtr = (BlockDBEntry*)ptr;
for (int i = 0; i < count; i++) {
if (entryPtr->TimeDelta < start) return;
for (int i = count - 1; i >= 0; i--) {
if (entryPtr->TimeDelta < start) return true;
if (entryPtr->TimeDelta <= end) {
for (int j = 0; j < ids.Length; j++) {
if (entryPtr->PlayerID == ids[j]) {
output(*entryPtr); break;
}
if (entryPtr->PlayerID != ids[j]) continue;
output(*entryPtr); break;
}
}
entryPtr++;
entryPtr--;
}
entries -= count;
}
}
return false;
}

View File

@ -36,7 +36,7 @@ namespace MCGalaxy.DB {
}
}
public static List<int> FindIds(string name) {
public static int[] FindIds(string name) {
List<string> invalid = Server.invalidIds.All();
List<int> ids = new List<int>();
@ -49,7 +49,7 @@ namespace MCGalaxy.DB {
ids.Add(PlayerData.ParseInt(raw));
}
}
return ids;
return ids.ToArray();
}
public static int InvalidNameID(string name) {