mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-25 06:04:46 -04:00
DB: Now the new BlockDB format works. Still quite a bit to do though.
This commit is contained in:
parent
8485e00d91
commit
e878d4699b
@ -18,6 +18,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using MCGalaxy.DB;
|
||||
using MCGalaxy.SQL;
|
||||
using MCGalaxy.Util;
|
||||
|
||||
@ -46,14 +47,16 @@ namespace MCGalaxy.Commands {
|
||||
byte id = b;
|
||||
if (b == Block.custom_block)
|
||||
id = p.level.GetExtTile(x, y, z);
|
||||
Dictionary<int, string> names = new Dictionary<int, string>();
|
||||
|
||||
string blockName = p.level.BlockName(b, id);
|
||||
Player.Message(p, "Block ({0}, {1}, {2}): &f{3} = {4}%S.", x, y, z, id, blockName);
|
||||
bool foundAny = false;
|
||||
|
||||
ListFromDatabase(p, ref foundAny, x, y, z);
|
||||
// TODO: List from BlockDB file
|
||||
ListInMemory(p, ref foundAny, x, y, z);
|
||||
ListFromDatabase(p, ref foundAny, names, x, y, z);
|
||||
p.level.BlockDB.FindChangesAt(x, y, z,
|
||||
entry => OutputEntry(p, ref foundAny, names, entry));
|
||||
ListInMemory(p, ref foundAny, names, x, y, z);
|
||||
|
||||
if (!foundAny) Player.Message(p, "No block change records found for this block.");
|
||||
OutputMessageBlock(p, b, id, x, y, z);
|
||||
@ -63,7 +66,8 @@ namespace MCGalaxy.Commands {
|
||||
GC.WaitForPendingFinalizers();
|
||||
}
|
||||
|
||||
static void ListFromDatabase(Player p, ref bool foundAny, ushort x, ushort y, ushort z) {
|
||||
static void ListFromDatabase(Player p, ref bool foundAny, Dictionary<int, string> names,
|
||||
ushort x, ushort y, ushort z) {
|
||||
DataTable Blocks = Database.Backend.GetRows("Block" + p.level.name, "*",
|
||||
"WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z);
|
||||
DateTime now = DateTime.Now;
|
||||
@ -71,13 +75,13 @@ namespace MCGalaxy.Commands {
|
||||
for (int i = 0; i < Blocks.Rows.Count; i++) {
|
||||
foundAny = true;
|
||||
DataRow row = Blocks.Rows[i];
|
||||
string user = row["Username"].ToString().Trim();
|
||||
string name = row["Username"].ToString().Trim();
|
||||
DateTime time = DateTime.Parse(row["TimePerformed"].ToString());
|
||||
byte block = byte.Parse(row["Type"].ToString());
|
||||
|
||||
byte flags = ParseFlags(row["Deleted"].ToString());
|
||||
bool deleted = (flags & 1) != 0, isExt = (flags & 2) != 0;
|
||||
Output(p, user, block, isExt, deleted, now - time);
|
||||
Output(p, name, block, isExt, deleted, now - time);
|
||||
}
|
||||
Blocks.Dispose();
|
||||
}
|
||||
@ -89,22 +93,29 @@ namespace MCGalaxy.Commands {
|
||||
return byte.Parse(value);
|
||||
}
|
||||
|
||||
static void ListInMemory(Player p, ref bool foundAny, ushort x, ushort y, ushort z) {
|
||||
static void OutputEntry(Player p, ref bool foundAny, Dictionary<int, string> names, BlockDBEntry entry) {
|
||||
DateTime now = DateTime.UtcNow;
|
||||
string name = null;
|
||||
if (!names.TryGetValue(entry.PlayerID, out name)) {
|
||||
name = NameConverter.FindName(entry.PlayerID);
|
||||
names[entry.PlayerID] = name;
|
||||
}
|
||||
foundAny = true;
|
||||
|
||||
DateTime time = BlockDB.Epoch.AddSeconds(entry.TimeDelta);
|
||||
bool deleted = entry.NewRaw == 0;
|
||||
bool extBlock = (entry.Flags & 0x8000) != 0;
|
||||
Output(p, name, entry.NewRaw, extBlock, deleted, now - time);
|
||||
}
|
||||
|
||||
static void ListInMemory(Player p, ref bool foundAny, Dictionary<int, string> names,
|
||||
ushort x, ushort y, ushort z) {
|
||||
int index = p.level.PosToInt(x, y, z);
|
||||
DateTime now = DateTime.Now;
|
||||
FastList<BlockDBEntry> entries = p.level.blockCache;
|
||||
|
||||
for (int i = 0; i < entries.Count; i++) {
|
||||
if (entries.Items[i].Index != index) continue;
|
||||
|
||||
foundAny = true;
|
||||
BlockDBEntry entry = entries.Items[i];
|
||||
string user = entry.name.Trim();
|
||||
DateTime time = BlockDB.Epoch.AddSeconds(entry.TimeDelta);
|
||||
|
||||
bool deleted = entry.NewRaw != 0;
|
||||
bool extBlock = (entry.Flags & 0x8000) != 0;
|
||||
Output(p, user, entry.NewRaw, extBlock, deleted, now - time);
|
||||
if (entries.Items[i].Index != index) continue;
|
||||
OutputEntry(p, ref foundAny, names, entries.Items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System.IO;
|
||||
|
||||
namespace MCGalaxy.Commands {
|
||||
public sealed class CmdHide : Command {
|
||||
public override string name { get { return "hide"; } }
|
||||
|
@ -19,7 +19,7 @@ using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace MCGalaxy {
|
||||
namespace MCGalaxy.DB {
|
||||
|
||||
public unsafe partial class BlockDB {
|
||||
|
||||
@ -33,13 +33,12 @@ namespace MCGalaxy {
|
||||
public string MapName;
|
||||
|
||||
/// <summary> The path of this BlockDB's backing file on disc. </summary>
|
||||
public string FilePath { get { return "blockdefs/" + MapName + ".cbdb"; } }
|
||||
public string FilePath { get { return "blockdb/" + MapName + ".cbdb"; } }
|
||||
|
||||
/// <summary> Base point in time that all time deltas are offset from.</summary>
|
||||
public static DateTime Epoch = new DateTime(2000, 1, 1, 1, 1, 1, DateTimeKind.Utc);
|
||||
|
||||
readonly ReaderWriterLockSlim locker;
|
||||
bool resizeRequired;
|
||||
public BlockDB(Level lvl) {
|
||||
MapName = lvl.name;
|
||||
Width = lvl.Width; Height = lvl.Height; Length = lvl.Length;
|
||||
@ -50,19 +49,18 @@ namespace MCGalaxy {
|
||||
/// Also recreates the backing file if dimensions on disc are less than those in memory. </summary>
|
||||
void ValidateBackingFile() {
|
||||
Vec3U16 dims;
|
||||
using (IDisposable writeLock = locker.AccquireWriteLock()) {
|
||||
if (!File.Exists(FilePath)) {
|
||||
using (Stream s = File.OpenWrite(FilePath)) {
|
||||
dims = new Vec3U16(Width, Height, Length);
|
||||
WriteHeader(s, dims);
|
||||
}
|
||||
} else {
|
||||
using (Stream s = File.OpenRead(FilePath)) {
|
||||
ReadHeader(s, out dims);
|
||||
}
|
||||
if (dims.X < Width || dims.Y < Height || dims.Z < Length) {
|
||||
ResizeBackingFile();
|
||||
}
|
||||
|
||||
if (!File.Exists(FilePath)) {
|
||||
using (Stream s = File.OpenWrite(FilePath)) {
|
||||
dims = new Vec3U16(Width, Height, Length);
|
||||
WriteHeader(s, dims);
|
||||
}
|
||||
} else {
|
||||
using (Stream s = File.OpenRead(FilePath)) {
|
||||
ReadHeader(s, out dims);
|
||||
}
|
||||
if (dims.X < Width || dims.Y < Height || dims.Z < Length) {
|
||||
ResizeBackingFile();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -74,13 +72,13 @@ namespace MCGalaxy {
|
||||
|
||||
|
||||
static void WriteHeader(Stream s, Vec3U16 dims) {
|
||||
byte[] header = new byte[entrySize];
|
||||
byte[] header = new byte[entrySize * 4];
|
||||
NetUtils.WriteAscii("CBDB_MCG", header, 0);
|
||||
WriteU16(version, header, 8);
|
||||
WriteU16(dims.X, header, 10);
|
||||
WriteU16(dims.Y, header, 12);
|
||||
WriteU16(dims.Z, header, 14);
|
||||
s.Write(header, 0, header.Length);
|
||||
s.Write(header, 0, entrySize);
|
||||
}
|
||||
|
||||
static void ReadHeader(Stream s, out Vec3U16 dims) {
|
@ -20,7 +20,7 @@ using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using MCGalaxy.Util;
|
||||
|
||||
namespace MCGalaxy {
|
||||
namespace MCGalaxy.DB {
|
||||
|
||||
public unsafe partial class BlockDB {
|
||||
|
55
MCGalaxy/Database/BlockDB/NameConverter.cs
Normal file
55
MCGalaxy/Database/BlockDB/NameConverter.cs
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
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.Data;
|
||||
using MCGalaxy.SQL;
|
||||
|
||||
namespace MCGalaxy.DB {
|
||||
|
||||
/// <summary> Converts names to integer ids and back </summary>
|
||||
public static class NameConverter {
|
||||
|
||||
public static string FindName(int id) {
|
||||
List<string> invalid = Server.invalidIds.All();
|
||||
if (id > int.MaxValue - invalid.Count)
|
||||
return invalid[int.MaxValue - id];
|
||||
|
||||
using (DataTable ids = Database.Backend.GetRows("Players", "Name", "WHERE ID=@0", id)) {
|
||||
if (ids.Rows.Count == 0) return null;
|
||||
return ids.Rows[0]["Name"].ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public static List<int> FindIds(string name) {
|
||||
List<string> invalid = Server.invalidIds.All();
|
||||
List<int> ids = new List<int>();
|
||||
|
||||
int index = invalid.IndexOf(name.ToLower());
|
||||
if (index >= 0) ids.Add(int.MaxValue - index);
|
||||
|
||||
using (DataTable names = Database.Backend.GetRows("Players", "ID", "WHERE Name=@0", name)) {
|
||||
foreach (DataRow row in names.Rows) {
|
||||
string raw = row["ID"].ToString();
|
||||
ids.Add(PlayerData.ParseInt(raw));
|
||||
}
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MCGalaxy.Blocks.Physics;
|
||||
using MCGalaxy.DB;
|
||||
using MCGalaxy.Games;
|
||||
using MCGalaxy.SQL;
|
||||
|
||||
@ -428,14 +429,22 @@ namespace MCGalaxy {
|
||||
}
|
||||
|
||||
public void AddToBlockDB(Player p, int index, byte block, byte extBlock, bool delete) {
|
||||
if (!UseBlockDB) return;
|
||||
BlockPos bP = default(BlockPos);
|
||||
bP.name = p.name;
|
||||
bP.index = index;
|
||||
if (!UseBlockDB) return;
|
||||
BlockDBEntry entry;
|
||||
entry.PlayerID = p.UserID;
|
||||
entry.TimeDelta = (int)DateTime.UtcNow.Subtract(BlockDB.Epoch).TotalSeconds;
|
||||
entry.Index = index;
|
||||
|
||||
bP.SetData(block, extBlock, delete);
|
||||
entry.OldRaw = Block.Invalid; // TODO: need to fill out old block properly
|
||||
entry.NewRaw = delete ? Block.air : block;
|
||||
entry.Flags = 0x1;
|
||||
|
||||
if (block == Block.custom_block) {
|
||||
entry.Flags |= 0x8000;
|
||||
entry.NewRaw = extBlock;
|
||||
}
|
||||
lock (blockCacheLock)
|
||||
blockCache.Add(bP);
|
||||
blockCache.Add(entry);
|
||||
}
|
||||
|
||||
public void UpdateBlock(Player p, ushort x, ushort y, ushort z,
|
||||
|
@ -20,6 +20,7 @@ using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using MCGalaxy.Blocks;
|
||||
using MCGalaxy.Blocks.Physics;
|
||||
using MCGalaxy.DB;
|
||||
using MCGalaxy.Config;
|
||||
using MCGalaxy.Games;
|
||||
using MCGalaxy.Util;
|
||||
|
@ -20,6 +20,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using MCGalaxy.Blocks;
|
||||
using MCGalaxy.DB;
|
||||
using MCGalaxy.Games;
|
||||
using MCGalaxy.Generator;
|
||||
using MCGalaxy.Levels.IO;
|
||||
@ -476,25 +477,6 @@ namespace MCGalaxy {
|
||||
return onLevel;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct BlockPos {
|
||||
public string name;
|
||||
public int flags, index; // bit 0 = is deleted, bit 1 = is ext, rest bits = time delta
|
||||
public byte rawBlock;
|
||||
|
||||
public void SetData(byte block, byte extBlock, bool delete) {
|
||||
TimeSpan delta = DateTime.UtcNow.Subtract(Server.StartTime);
|
||||
flags = (int)delta.TotalSeconds << 2;
|
||||
flags |= (byte)(delete ? 1 : 0);
|
||||
|
||||
if (block == Block.custom_block) {
|
||||
rawBlock = extBlock; flags |= 2;
|
||||
} else {
|
||||
rawBlock = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct UndoPos {
|
||||
public int flags, index; // bit 0 = is old ext, bit 1 = is new ext, rest bits = time delta
|
||||
|
@ -407,8 +407,9 @@
|
||||
<Compile Include="CorePlugin\CorePlugin.cs" />
|
||||
<Compile Include="CorePlugin\ConnectHandler.cs" />
|
||||
<Compile Include="Database\Backends\SQLite.cs" />
|
||||
<Compile Include="Database\BlockDB.cs" />
|
||||
<Compile Include="Database\BlockDB.Utils.cs" />
|
||||
<Compile Include="Database\BlockDB\BlockDB.cs" />
|
||||
<Compile Include="Database\BlockDB\BlockDB.Utils.cs" />
|
||||
<Compile Include="Database\BlockDB\NameConverter.cs" />
|
||||
<Compile Include="Database\ColumnDesc.cs" />
|
||||
<Compile Include="Database\IDatabaseBackend.cs" />
|
||||
<Compile Include="Database\Backends\MySQL.cs" />
|
||||
@ -713,6 +714,7 @@
|
||||
<Folder Include="Commands\World" />
|
||||
<Folder Include="Commands\other" />
|
||||
<Folder Include="Database\Backends" />
|
||||
<Folder Include="Database\BlockDB" />
|
||||
<Folder Include="Drawing\DrawOps" />
|
||||
<Folder Include="Drawing\Brushes" />
|
||||
<Folder Include="Drawing\Image" />
|
||||
|
@ -53,14 +53,13 @@ namespace MCGalaxy {
|
||||
|
||||
/// <summary> Adds or replaces the given name,
|
||||
/// returning the index of the item within the list. </summary>
|
||||
public int AddOrReplace(string p) {
|
||||
public void AddOrReplace(string p) {
|
||||
p = p.ToLower();
|
||||
lock (locker) {
|
||||
int idx = players.IndexOf(p);
|
||||
if (idx >= 0) return idx;
|
||||
if (idx >= 0) return;
|
||||
|
||||
players.Add(p);
|
||||
return players.Count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Threading;
|
||||
using MCGalaxy.DB;
|
||||
using MCGalaxy.Games;
|
||||
using MCGalaxy.SQL;
|
||||
using MCGalaxy.Undo;
|
||||
|
@ -19,7 +19,7 @@ using System;
|
||||
using System.Data;
|
||||
using MCGalaxy.SQL;
|
||||
|
||||
namespace MCGalaxy {
|
||||
namespace MCGalaxy {
|
||||
public class PlayerData {
|
||||
public string Name, Color, Title, TitleColor, TotalTime, IP;
|
||||
public DateTime FirstLogin, LastLogin;
|
||||
@ -46,13 +46,14 @@ namespace MCGalaxy {
|
||||
"totalDeaths, Money, totalBlocks, totalKicked, TimeSpent",
|
||||
p.name, p.ip, now, now, 1, "", 0, 0, 0, 0, p.time.ToDBTime());
|
||||
|
||||
using (DataTable ids = Database.Backend.GetRows("Players",
|
||||
"ID", "WHERE Name = @0", p.name)) {
|
||||
using (DataTable ids = Database.Backend.GetRows("Players",
|
||||
"ID", "WHERE Name = @0", p.name)) {
|
||||
if (ids.Rows.Count > 0) {
|
||||
string id = ids.Rows[0]["ID"].ToString();
|
||||
p.UserID = PlayerData.ParseInt(id);
|
||||
} else {
|
||||
int index = Server.invalidIds.AddOrReplace(p.name);
|
||||
Server.invalidIds.AddOrReplace(p.name);
|
||||
int index = Server.invalidIds.All().IndexOf(p.name.ToLower());
|
||||
p.UserID = int.MaxValue - index;
|
||||
}
|
||||
}
|
||||
@ -126,7 +127,7 @@ namespace MCGalaxy {
|
||||
|
||||
// Try parse color name, then color code
|
||||
string parsed = Colors.Parse(col);
|
||||
if (parsed != "") return parsed;
|
||||
if (parsed != "") return parsed;
|
||||
return Colors.Name(col) == "" ? "" : col;
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,8 @@ namespace MCGalaxy {
|
||||
};
|
||||
|
||||
void InitDatabase() {
|
||||
if (!Directory.Exists("blockdb")) Directory.CreateDirectory("blockdb");
|
||||
|
||||
try {
|
||||
Database.Backend.CreateDatabase();
|
||||
} catch (Exception e) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user