mirror of
https://github.com/ClassiCube/MCGalaxy.git
synced 2025-09-23 04:32:50 -04:00
Initial WIP on database rewrite
This commit is contained in:
parent
5857321031
commit
fde77c5542
@ -18,32 +18,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using MCGalaxy.Maths;
|
||||
using MCGalaxy.SQL;
|
||||
|
||||
namespace MCGalaxy.Blocks.Extended {
|
||||
public static class MessageBlock {
|
||||
public static class MessageBlock {
|
||||
|
||||
public static bool Handle(Player p, ushort x, ushort y, ushort z, bool alwaysRepeat) {
|
||||
if (!p.level.hasMessageBlocks) return false;
|
||||
|
||||
try {
|
||||
DataTable Messages = Database.Backend.GetRows("Messages" + p.level.name, "*",
|
||||
"WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z);
|
||||
int last = Messages.Rows.Count - 1;
|
||||
if (last == -1) { Messages.Dispose(); return false; }
|
||||
string message = Get(p.level.MapName, x, y, z);
|
||||
if (message == null) return false;
|
||||
message = message.Replace("@p", p.name);
|
||||
|
||||
string message = Messages.Rows[last]["Message"].ToString().Trim();
|
||||
message = message.Replace("\\'", "\'");
|
||||
message = message.Cp437ToUnicode();
|
||||
message = message.Replace("@p", p.name);
|
||||
|
||||
if (message != p.prevMsg || (alwaysRepeat || ServerConfig.RepeatMBs)) {
|
||||
Execute(p, message);
|
||||
}
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
if (message != p.prevMsg || (alwaysRepeat || ServerConfig.RepeatMBs)) {
|
||||
Execute(p, message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void Execute(Player p, string message) {
|
||||
@ -75,13 +66,13 @@ namespace MCGalaxy.Blocks.Extended {
|
||||
Command.Search(ref cmdName, ref cmdArgs);
|
||||
|
||||
Command cmd = Command.Find(cmdName);
|
||||
if (cmd == null) return true;
|
||||
if (cmd == null) return true;
|
||||
bool mbUseable = !cmd.MessageBlockRestricted && !cmd.type.CaselessContains("mod");
|
||||
|
||||
if (p.group.CanExecute(cmd) && (allCmds || mbUseable)) return true;
|
||||
Player.Message(p, "You cannot use %T/{0} %Sin a messageblock.", cmd.name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static string[] sep = new string[] { " |/" };
|
||||
const StringSplitOptions opts = StringSplitOptions.RemoveEmptyEntries;
|
||||
@ -106,5 +97,38 @@ namespace MCGalaxy.Blocks.Extended {
|
||||
text = message; return empty;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static object IterateAll(IDataRecord record, object arg) {
|
||||
Vec3U16 pos;
|
||||
pos.X = (ushort)record.GetInt32(0);
|
||||
pos.Y = (ushort)record.GetInt32(1);
|
||||
pos.Z = (ushort)record.GetInt32(2);
|
||||
|
||||
((List<Vec3U16>)arg).Add(pos);
|
||||
return arg;
|
||||
}
|
||||
|
||||
internal static List<Vec3U16> GetAll(string map) {
|
||||
List<Vec3U16> coords = new List<Vec3U16>();
|
||||
Database.Backend.IterateRows("Messages" + map, "X,Y,Z",
|
||||
coords, IterateAll);
|
||||
return coords;
|
||||
}
|
||||
|
||||
internal static string Get(string map, ushort x, ushort y, ushort z) {
|
||||
string msg = Database.GetString("Messages" + map, "Message",
|
||||
"WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z);
|
||||
if (msg == null) return null;
|
||||
|
||||
msg = msg.Trim().Replace("\\'", "\'");
|
||||
msg = msg.Cp437ToUnicode();
|
||||
return msg;
|
||||
}
|
||||
|
||||
internal static void Delete(string map, ushort x, ushort y, ushort z) {
|
||||
Database.Backend.DeleteRows("Messages" + map,
|
||||
"WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
@ -22,41 +22,55 @@ using MCGalaxy.SQL;
|
||||
namespace MCGalaxy.Blocks.Extended {
|
||||
public static class Portal {
|
||||
|
||||
public class PortalExitData {
|
||||
public string Map;
|
||||
public int X, Y, Z;
|
||||
}
|
||||
|
||||
static object IteratePortalExit(IDataRecord record, object arg) {
|
||||
PortalExitData data = new PortalExitData();
|
||||
data.Map = record.GetString("ExitMap");
|
||||
data.X = record.GetInt32("ExitX");
|
||||
data.Y = record.GetInt32("ExitY");
|
||||
data.Z = record.GetInt32("ExitZ");
|
||||
|
||||
data.Map = data.Map.Cp437ToUnicode();
|
||||
return data;
|
||||
}
|
||||
|
||||
public static PortalExitData Get(string map, ushort x, ushort y, ushort z) {
|
||||
object raw = Database.Backend.IterateRows("Portals" + map, "*", null, IteratePortalExit,
|
||||
"WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2", x, y, z);
|
||||
return (PortalExitData)raw;
|
||||
}
|
||||
|
||||
public static bool Handle(Player p, ushort x, ushort y, ushort z) {
|
||||
if (!p.level.hasPortals) return false;
|
||||
|
||||
try {
|
||||
DataTable Portals = Database.Backend.GetRows("Portals" + p.level.name, "*",
|
||||
"WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2", x, y, z);
|
||||
int last = Portals.Rows.Count - 1;
|
||||
if (last == -1) { Portals.Dispose(); return false; }
|
||||
Orientation rot = p.Rot;
|
||||
PortalExitData exit = Get(p.level.MapName, x, y, z);
|
||||
if (exit == null) return false;
|
||||
Orientation rot = p.Rot;
|
||||
|
||||
if (p.level.name != exit.Map) {
|
||||
Level curLevel = p.level;
|
||||
p.summonedMap = exit.Map;
|
||||
bool changedMap = false;
|
||||
|
||||
DataRow row = Portals.Rows[last];
|
||||
string map = row["ExitMap"].ToString();
|
||||
map = map.Cp437ToUnicode();
|
||||
|
||||
if (p.level.name != map) {
|
||||
Level curLevel = p.level;
|
||||
p.summonedMap = map;
|
||||
bool changedMap = PlayerActions.ChangeMap(p, map);
|
||||
p.summonedMap = null;
|
||||
|
||||
if (!changedMap) { Player.Message(p, "Unable to use this portal, as this portal goes to that map."); return true; }
|
||||
p.BlockUntilLoad(10);
|
||||
try {
|
||||
changedMap = PlayerActions.ChangeMap(p, exit.Map);
|
||||
} catch (Exception ex) {
|
||||
Logger.LogError(ex);
|
||||
changedMap = false;
|
||||
}
|
||||
|
||||
x = ushort.Parse(row["ExitX"].ToString());
|
||||
y = ushort.Parse(row["ExitY"].ToString());
|
||||
z = ushort.Parse(row["ExitZ"].ToString());
|
||||
|
||||
Position pos = Position.FromFeetBlockCoords(x, y, z);
|
||||
p.SendPos(Entities.SelfID, pos, rot);
|
||||
Portals.Dispose();
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
p.summonedMap = null;
|
||||
if (!changedMap) { Player.Message(p, "Unable to use this portal, as this portal goes to that map."); return true; }
|
||||
p.BlockUntilLoad(10);
|
||||
}
|
||||
|
||||
Position pos = Position.FromFeetBlockCoords(exit.X, exit.Y, exit.Z);
|
||||
p.SendPos(Entities.SelfID, pos, rot);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,6 +16,7 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using MCGalaxy.SQL;
|
||||
|
||||
@ -25,19 +26,27 @@ namespace MCGalaxy.Commands.Chatting {
|
||||
public override string type { get { return CommandTypes.Chat; } }
|
||||
public override bool SuperUseable { get { return false; } }
|
||||
|
||||
public override void Use(Player p, string message) {
|
||||
if (!Database.TableExists("Inbox" + p.name)) {
|
||||
class MailEntry { public string Contents, Timestamp, From; }
|
||||
static object IterateInbox(IDataRecord record, object arg) {
|
||||
MailEntry e = new MailEntry();
|
||||
e.Contents = record.GetString("Contents");
|
||||
e.Timestamp = record.GetString("TimeSent");
|
||||
e.From = record.GetString("PlayerFrom");
|
||||
|
||||
((List<MailEntry>)arg).Add(e); return arg;
|
||||
}
|
||||
|
||||
public override void Use(Player p, string message) {
|
||||
List<MailEntry> entries = new List<MailEntry>();
|
||||
Database.Backend.IterateRows("Inbox" + p.name, "*",
|
||||
entries, IterateInbox, "ORDER BY TimeSent");
|
||||
if (entries.Count == 0) {
|
||||
Player.Message(p, "Your inbox is empty."); return;
|
||||
}
|
||||
|
||||
string[] args = message.SplitSpaces(2);
|
||||
if (message.Length == 0) {
|
||||
using (DataTable Inbox = Database.Backend.GetRows("Inbox" + p.name, "*", "ORDER BY TimeSent")) {
|
||||
if (Inbox.Rows.Count == 0) { Player.Message(p, "No messages found."); return; }
|
||||
foreach (DataRow row in Inbox.Rows) {
|
||||
OutputMessage(p, row);
|
||||
}
|
||||
}
|
||||
foreach (MailEntry entry in entries) { Output(p, entry); }
|
||||
} else if (IsDeleteCommand(args[0])) {
|
||||
if (args.Length == 1) {
|
||||
Player.Message(p, "You need to provide either \"all\" or a number."); return;
|
||||
@ -45,50 +54,44 @@ namespace MCGalaxy.Commands.Chatting {
|
||||
Database.Backend.ClearTable("Inbox" + p.name);
|
||||
Player.Message(p, "Deleted all messages.");
|
||||
} else {
|
||||
DeleteMessageByID(p, args[1]);
|
||||
DeleteByID(p, args[1], entries);
|
||||
}
|
||||
} else {
|
||||
OutputMessageByID(p, message);
|
||||
OutputByID(p, message, entries);
|
||||
}
|
||||
}
|
||||
|
||||
static void DeleteMessageByID(Player p, string value) {
|
||||
int num = 0;
|
||||
if (!CommandParser.GetInt(p, value, "Message number", ref num, 0)) return;
|
||||
static void DeleteByID(Player p, string value, List<MailEntry> entries) {
|
||||
int num = 1;
|
||||
if (!CommandParser.GetInt(p, value, "Message number", ref num, 1)) return;
|
||||
|
||||
using (DataTable Inbox = Database.Backend.GetRows("Inbox" + p.name, "*", "ORDER BY TimeSent")) {
|
||||
if (num >= Inbox.Rows.Count) {
|
||||
Player.Message(p, "Message #{0} does not exist.", num); return;
|
||||
}
|
||||
|
||||
DataRow row = Inbox.Rows[num];
|
||||
string time = Convert.ToDateTime(row["TimeSent"]).ToString("yyyy-MM-dd HH:mm:ss");
|
||||
if (num > entries.Count) {
|
||||
Player.Message(p, "Message #{0} does not exist.", num);
|
||||
} else {
|
||||
MailEntry entry = entries[num - 1];
|
||||
Database.Backend.DeleteRows("Inbox" + p.name,
|
||||
"WHERE PlayerFrom=@0 AND TimeSent=@1", row["PlayerFrom"], time);
|
||||
|
||||
"WHERE PlayerFrom=@0 AND TimeSent=@1", entry.From, entry.Timestamp);
|
||||
Player.Message(p, "Deleted message #{0}", num);
|
||||
}
|
||||
}
|
||||
|
||||
static void OutputMessageByID(Player p, string value) {
|
||||
int num = 0;
|
||||
if (!CommandParser.GetInt(p, value, "Message number", ref num, 0)) return;
|
||||
|
||||
using (DataTable Inbox = Database.Backend.GetRows("Inbox" + p.name, "*", "ORDER BY TimeSent")) {
|
||||
if (num >= Inbox.Rows.Count) {
|
||||
Player.Message(p, "Message #{0} does not exist.", num); return;
|
||||
}
|
||||
|
||||
OutputMessage(p, Inbox.Rows[num]);
|
||||
static void OutputByID(Player p, string value, List<MailEntry> entries) {
|
||||
int num = 1;
|
||||
if (!CommandParser.GetInt(p, value, "Message number", ref num, 1)) return;
|
||||
|
||||
if (num > entries.Count) {
|
||||
Player.Message(p, "Message #{0} does not exist.", num);
|
||||
} else {
|
||||
Output(p, entries[num - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
static void OutputMessage(Player p, DataRow row) {
|
||||
DateTime time = Convert.ToDateTime(row["TimeSent"]);
|
||||
TimeSpan delta = DateTime.Now - time;
|
||||
string sender = PlayerInfo.GetColoredName(p, row["PlayerFrom"].ToString());
|
||||
static void Output(Player p, MailEntry entry) {
|
||||
TimeSpan delta = DateTime.Now - Convert.ToDateTime(entry.Timestamp);
|
||||
string sender = PlayerInfo.GetColoredName(p, entry.From);
|
||||
|
||||
Player.Message(p, "From {0} &a{1} ago:", sender, delta.Shorten());
|
||||
Player.Message(p, row["Contents"].ToString());
|
||||
Player.Message(p, entry.Contents);
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
|
@ -50,9 +50,7 @@ namespace MCGalaxy.Commands {
|
||||
|
||||
static List<CommandExtraPerms> list = new List<CommandExtraPerms>();
|
||||
|
||||
|
||||
/// <summary> Finds the nth extra permission for a given command. </summary>
|
||||
/// <returns> null if the nth extra permission does not exist. </returns>
|
||||
|
||||
public static CommandExtraPerms Find(string cmd, int num = 1) {
|
||||
foreach (CommandExtraPerms perms in list) {
|
||||
if (perms.CmdName.CaselessEq(cmd) && perms.Number == num) return perms;
|
||||
@ -60,18 +58,13 @@ namespace MCGalaxy.Commands {
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary> Returns the lowest rank that has the nth extra permission for a given command. </summary>
|
||||
/// <returns> defPerm if the nth extra permission does not exist, otherwise the lowest rank. </returns>
|
||||
public static LevelPermission MinPerm(string cmd, LevelPermission defPerm, int num = 1) {
|
||||
CommandExtraPerms perms = Find(cmd, num);
|
||||
return perms == null ? defPerm : perms.MinRank;
|
||||
}
|
||||
|
||||
/// <summary> Returns the lowest rank that has the nth extra permission for a given command. </summary>
|
||||
public static LevelPermission MinPerm(string cmd, int num = 1) { return Find(cmd, num).MinRank; }
|
||||
|
||||
/// <summary> Finds all extra permissions for a given command. </summary>
|
||||
/// <remarks> list is empty when no extra permissions are found, not null. </remarks>
|
||||
|
||||
public static List<CommandExtraPerms> FindAll(string cmd) {
|
||||
List<CommandExtraPerms> allPerms = new List<CommandExtraPerms>();
|
||||
foreach (CommandExtraPerms perms in list) {
|
||||
|
@ -130,7 +130,7 @@ namespace MCGalaxy.Commands.Info {
|
||||
|
||||
Player.Message(p, "Block \"{0}\" appears as &b{1}",
|
||||
message, Block.GetName(p, Block.Convert(b)));
|
||||
BlockPerms.List[b].MessageCannotUse(p, "use");
|
||||
BlockPerms.List[b].MessageCannotUse(p, "use");
|
||||
DescribePhysics(p, message, b);
|
||||
return true;
|
||||
}
|
||||
|
@ -64,23 +64,23 @@ namespace MCGalaxy.Commands.Info {
|
||||
Player.Message(p, "OpStats for {0} %Ssince {1}",
|
||||
PlayerInfo.GetColoredName(p, name), start);
|
||||
|
||||
int reviews = Query(start, end, name, "review", "LIKE 'next'");
|
||||
int ranks = Query(start, end, name, "setrank", "!=''");
|
||||
int promotes = Query(start, end, name, "setrank", "LIKE '+up%'");
|
||||
int demotes = Query(start, end, name, "setrank", "LIKE '-down%'");
|
||||
int promotesOld = Query(start, end, name, "promote");
|
||||
int demotesOld = Query(start, end, name, "demote");
|
||||
int reviews = Count(start, end, name, "review", "LIKE 'next'");
|
||||
int ranks = Count(start, end, name, "setrank", "!=''");
|
||||
int promotes = Count(start, end, name, "setrank", "LIKE '+up%'");
|
||||
int demotes = Count(start, end, name, "setrank", "LIKE '-down%'");
|
||||
int promotesOld = Count(start, end, name, "promote");
|
||||
int demotesOld = Count(start, end, name, "demote");
|
||||
|
||||
int mutes = Query(start, end, name, "mute");
|
||||
int freezes = Query(start, end, name, "freeze");
|
||||
int warns = Query(start, end, name, "warn");
|
||||
int kicks = Query(start, end, name, "kick");
|
||||
int mutes = Count(start, end, name, "mute");
|
||||
int freezes = Count(start, end, name, "freeze");
|
||||
int warns = Count(start, end, name, "warn");
|
||||
int kicks = Count(start, end, name, "kick");
|
||||
|
||||
int bans = Query(start, end, name, "ban");
|
||||
int kickbans = Query(start, end, name, "kickban");
|
||||
int ipbans = Query(start, end, name, "banip");
|
||||
int xbans = Query(start, end, name, "xban");
|
||||
int tempbans = Query(start, end, name, "tempban");
|
||||
int bans = Count(start, end, name, "ban");
|
||||
int kickbans = Count(start, end, name, "kickban");
|
||||
int ipbans = Count(start, end, name, "banip");
|
||||
int xbans = Count(start, end, name, "xban");
|
||||
int tempbans = Count(start, end, name, "tempban");
|
||||
|
||||
Player.Message(p, " &a{0}%S bans, &a{1}%S IP-bans, &a{2}%S tempbans",
|
||||
bans + kickbans + xbans, ipbans + xbans, tempbans);
|
||||
@ -94,14 +94,10 @@ namespace MCGalaxy.Commands.Info {
|
||||
static bool ValidTimespan(string value) {
|
||||
return value == "today" || value == "yesterday" || value == "thismonth" || value == "lastmonth" || value == "all";
|
||||
}
|
||||
|
||||
static int Query(string start, string end, string name, string cmd, string msg = "!=''") {
|
||||
using (DataTable table = Database.Backend.GetRows(
|
||||
"Opstats", "COUNT(ID)" ,"WHERE Time >= @0 AND Time < @1 AND " +
|
||||
"Name LIKE @2 AND Cmd LIKE @3 AND Cmdmsg " + msg, start, end, name, cmd)) {
|
||||
string count = table.Rows[0]["COUNT(id)"].ToString();
|
||||
return PlayerData.ParseInt(count);
|
||||
}
|
||||
|
||||
static int Count(string start, string end, string name, string cmd, string msg = "!=''") {
|
||||
const string whereSQL = "WHERE Time >= @0 AND Time < @1 AND Name LIKE @2 AND Cmd LIKE @3 AND Cmdmsg ";
|
||||
return Database.CountRows("Opstats", whereSQL + msg, start, end, name, cmd);
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
|
@ -35,13 +35,14 @@ namespace MCGalaxy.Commands.Info {
|
||||
|
||||
static PerformanceCounter allPCounter = null;
|
||||
static PerformanceCounter cpuPCounter = null;
|
||||
|
||||
|
||||
public override void Use(Player p, string message) {
|
||||
if (message.Length > 0) { Help(p); return; }
|
||||
|
||||
int count = Database.CountRows("Players");
|
||||
Player.Message(p, "Server's name: &b{0}%S", ServerConfig.Name);
|
||||
Player.Message(p, "&a{0} %Splayers total. (&a{1} %Sonline, &8{2} banned%S)",
|
||||
GetPlayerCount(), PlayerInfo.Online.Count, Group.BannedRank.Players.Count);
|
||||
count, PlayerInfo.Online.Count, Group.BannedRank.Players.Count);
|
||||
Player.Message(p, "&a{0} %Slevels currently loaded. Currency is &3{1}%S.",
|
||||
LevelInfo.Loaded.Count, ServerConfig.Currency);
|
||||
|
||||
@ -59,13 +60,7 @@ namespace MCGalaxy.Commands.Info {
|
||||
|
||||
if (HasExtraPerm(p, 1)) ShowServerStats(p);
|
||||
}
|
||||
|
||||
static int GetPlayerCount() {
|
||||
using (DataTable table = Database.Backend.GetRows("Players", "COUNT(id)")) {
|
||||
return int.Parse(table.Rows[0]["COUNT(id)"].ToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ShowServerStats(Player p) {
|
||||
Process proc = Process.GetCurrentProcess();
|
||||
if (allPCounter == null) {
|
||||
|
@ -178,32 +178,27 @@ namespace MCGalaxy.Commands.Maintenance {
|
||||
|
||||
|
||||
static void UpdateDB(string name, string value, string column) {
|
||||
Database.Backend.UpdateRows("Players", column + " = @1", "WHERE Name = @0", name, value.UnicodeToCp437());
|
||||
Database.Backend.UpdateRows("Players", column + " = @1",
|
||||
"WHERE Name = @0", name, value.UnicodeToCp437());
|
||||
}
|
||||
|
||||
static object IterateSetLong(IDataRecord record, object arg) { return record.GetInt64(0); }
|
||||
static long GetLong(string name, string column) {
|
||||
return (long)Database.Backend.IterateRows("Players", column, null, IterateSetLong,
|
||||
"WHERE Name = @0", name);
|
||||
}
|
||||
|
||||
// special case handling for packed forms of totalBlocks and totalCuboided
|
||||
static void UpdateDBLo(string name, string value, string column) {
|
||||
long loValue = long.Parse(value);
|
||||
// OR with existing high bits of value in DB
|
||||
using (DataTable results = Database.Backend.GetRows("Players", column, "WHERE Name = @0", name)) {
|
||||
if (results.Rows.Count > 0) {
|
||||
long curValue = PlayerData.ParseLong(results.Rows[0][column].ToString());
|
||||
loValue |= (curValue & ~PlayerData.LowerBitsMask);
|
||||
}
|
||||
}
|
||||
Database.Backend.UpdateRows("Players", column + " = @1", "WHERE Name = @0", name, loValue);
|
||||
long packed = GetLong(name, column) & ~PlayerData.LowerBitsMask; // hi value only
|
||||
packed |= long.Parse(value);
|
||||
UpdateDB(name, packed.ToString(), column);
|
||||
}
|
||||
|
||||
static void UpdateDBHi(string name, string value, string column) {
|
||||
long hiValue = long.Parse(value) << PlayerData.LowerBits;
|
||||
// OR with existing low bits of value in DB
|
||||
using (DataTable results = Database.Backend.GetRows("Players", column, "WHERE Name = @0", name)) {
|
||||
if (results.Rows.Count > 0) {
|
||||
long curValue = PlayerData.ParseLong(results.Rows[0][column].ToString());
|
||||
hiValue |= (curValue & PlayerData.LowerBitsMask);
|
||||
}
|
||||
}
|
||||
Database.Backend.UpdateRows("Players", column + " = @1", "WHERE Name = @0", name, hiValue);
|
||||
long packed = GetLong(name, column) & PlayerData.LowerBitsMask; // lo value only
|
||||
packed |= long.Parse(value) << PlayerData.LowerBits;
|
||||
UpdateDB(name, packed.ToString(), column);
|
||||
}
|
||||
|
||||
static void MessageDataChanged(Player p, string name, string type, string value) {
|
||||
|
@ -103,23 +103,19 @@ namespace MCGalaxy.Commands.Building {
|
||||
args.Message = Colors.Escape(args.Message);
|
||||
args.Message = args.Message.UnicodeToCp437();
|
||||
|
||||
string lvlName = p.level.name;
|
||||
object locker = ThreadSafeCache.DBCache.GetLocker(lvlName);
|
||||
string map = p.level.name;
|
||||
object locker = ThreadSafeCache.DBCache.GetLocker(map);
|
||||
|
||||
lock (locker) {
|
||||
Database.Backend.CreateTable("Messages" + lvlName, LevelDB.createMessages);
|
||||
Database.Backend.CreateTable("Messages" + map, LevelDB.createMessages);
|
||||
p.level.hasMessageBlocks = true;
|
||||
|
||||
int count = 0;
|
||||
using (DataTable Messages = Database.Backend.GetRows("Messages" + lvlName, "*",
|
||||
"WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z)) {
|
||||
count = Messages.Rows.Count;
|
||||
}
|
||||
|
||||
int count = Database.CountRows("Messages" + map,
|
||||
"WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z);
|
||||
if (count == 0) {
|
||||
Database.Backend.AddRow("Messages" + lvlName, "X, Y, Z, Message", x, y, z, args.Message);
|
||||
Database.Backend.AddRow("Messages" + map, "X, Y, Z, Message", x, y, z, args.Message);
|
||||
} else {
|
||||
Database.Backend.UpdateRows("Messages" + lvlName, "Message=@3",
|
||||
Database.Backend.UpdateRows("Messages" + map, "Message=@3",
|
||||
"WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z, args.Message);
|
||||
}
|
||||
}
|
||||
@ -130,32 +126,18 @@ namespace MCGalaxy.Commands.Building {
|
||||
|
||||
void ShowMessageBlocks(Player p) {
|
||||
p.showMBs = !p.showMBs;
|
||||
int count = 0;
|
||||
List<Vec3U16> coords = MessageBlock.GetAll(p.level.MapName);
|
||||
|
||||
if (p.level.hasMessageBlocks) {
|
||||
using (DataTable table = Database.Backend.GetRows("Messages" + p.level.name, "*")) {
|
||||
count = table.Rows.Count;
|
||||
if (p.showMBs) { ShowMessageBlocks(p, table); }
|
||||
else { HideMessageBlocks(p, table); }
|
||||
foreach (Vec3U16 pos in coords) {
|
||||
if (p.showMBs) {
|
||||
p.SendBlockchange(pos.X, pos.Y, pos.Z, Block.Green);
|
||||
} else {
|
||||
p.RevertBlock(pos.X, pos.Y, pos.Z);
|
||||
}
|
||||
}
|
||||
Player.Message(p, "Now {0} %SMBs.", p.showMBs ? "showing &a" + count : "hiding");
|
||||
}
|
||||
|
||||
static void ShowMessageBlocks(Player p, DataTable table) {
|
||||
foreach (DataRow row in table.Rows) {
|
||||
p.SendBlockchange(U16(row["X"]), U16(row["Y"]), U16(row["Z"]), Block.Green);
|
||||
}
|
||||
}
|
||||
|
||||
static void HideMessageBlocks(Player p, DataTable table) {
|
||||
foreach (DataRow row in table.Rows) {
|
||||
p.RevertBlock(U16(row["X"]), U16(row["Y"]), U16(row["Z"]));
|
||||
}
|
||||
}
|
||||
|
||||
static ushort U16(object x) { return Convert.ToUInt16(x); }
|
||||
|
||||
Player.Message(p, "Now {0} %SMBs.", p.showMBs ? "showing &a" + coords.Count : "hiding");
|
||||
}
|
||||
|
||||
static string Format(BlockID block, Player p, BlockProps[] props) {
|
||||
if (!props[block].IsMessageBlock) return null;
|
||||
|
@ -116,15 +116,11 @@ namespace MCGalaxy.Commands.Building {
|
||||
|
||||
lock (locker) {
|
||||
Database.Backend.CreateTable("Portals" + lvlName, LevelDB.createPortals);
|
||||
Level map = LevelInfo.FindExact(P.Map);
|
||||
if (map != null) map.hasPortals = true;
|
||||
Level lvl = LevelInfo.FindExact(P.Map);
|
||||
if (lvl != null) lvl.hasPortals = true;
|
||||
|
||||
int count = 0;
|
||||
using (DataTable portals = Database.Backend.GetRows("Portals" + lvlName, "*",
|
||||
"WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2", P.x, P.y, P.z)) {
|
||||
count = portals.Rows.Count;
|
||||
}
|
||||
|
||||
int count = Database.CountRows("Portals" + lvlName,
|
||||
"WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2", P.x, P.y, P.z);
|
||||
if (count == 0) {
|
||||
Database.Backend.AddRow("Portals" + lvlName, "EntryX, EntryY, EntryZ, ExitX, ExitY, ExitZ, ExitMap",
|
||||
P.x, P.y, P.z, x, y, z, dstMap);
|
||||
@ -158,7 +154,7 @@ namespace MCGalaxy.Commands.Building {
|
||||
if (p.showPortals) { ShowPortals(p, table); }
|
||||
else { HidePortals(p, table); }
|
||||
}
|
||||
}
|
||||
}
|
||||
Player.Message(p, "Now {0} %Sportals.", p.showPortals ? "showing &a" + count : "hiding");
|
||||
}
|
||||
|
||||
|
83
MCGalaxy/Commands/building/CmdWrite2.cs
Normal file
83
MCGalaxy/Commands/building/CmdWrite2.cs
Normal file
@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using MCGalaxy.Commands.Building;
|
||||
using MCGalaxy.Drawing.Ops;
|
||||
using MCGalaxy.Drawing.Brushes;
|
||||
using MCGalaxy.Maths;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
namespace MCGalaxy.Commands {
|
||||
|
||||
public class Write2DrawOp : DrawOp {
|
||||
public override string Name { get { return "Write2"; } }
|
||||
public string Text;
|
||||
public override long BlocksAffected(Level lvl, Vec3S32[] marks) { return Text.Length; }
|
||||
|
||||
Vec3S32 dir, pos;
|
||||
public override void Perform(Vec3S32[] marks, Brush brush, DrawOpOutput output) {
|
||||
Vec3S32 p1 = marks[0], p2 = marks[1];
|
||||
if (Math.Abs(p2.X - p1.X) > Math.Abs(p2.Z - p1.Z)) {
|
||||
dir.X = p2.X > p1.X ? 1 : -1;
|
||||
} else {
|
||||
dir.Z = p2.Z > p1.Z ? 1 : -1;
|
||||
}
|
||||
|
||||
pos = p1;
|
||||
foreach (char c in Text) { DrawLetter(Player, c, output); }
|
||||
}
|
||||
|
||||
void DrawLetter(Player p, char c, DrawOpOutput output) {
|
||||
if ((int)c >= 256 || letters[c] == 0) {
|
||||
if (c != ' ') Player.Message(p, "\"{0}\" is not currently supported, replacing with space", c);
|
||||
} else {
|
||||
BlockID block = Block.FromRaw(letters[c]);
|
||||
output(Place((ushort)pos.X, (ushort)pos.Y, (ushort)pos.Z, block));
|
||||
}
|
||||
pos += dir;
|
||||
}
|
||||
|
||||
static BlockID[] letters;
|
||||
static Write2DrawOp() {
|
||||
letters = new BlockID[256];
|
||||
letters['.'] = 520;
|
||||
letters['!'] = 521;
|
||||
letters['/'] = 522;
|
||||
letters['?'] = 523;
|
||||
|
||||
for (int i = '0'; i <= '9'; i++) {
|
||||
letters[i] = (BlockID)(484 + (i - '0'));
|
||||
}
|
||||
for (int i = 'A'; i <= 'Z'; i++) {
|
||||
letters[i] = (BlockID)(494 + (i - 'A'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class CmdWrite2 : DrawCmd {
|
||||
public override string name { get { return "Write2"; } }
|
||||
public override LevelPermission defaultRank { get { return LevelPermission.AdvBuilder; } }
|
||||
|
||||
protected override string SelectionType { get { return "direction"; } }
|
||||
protected override string PlaceMessage { get { return "Place or break two blocks to determine direction."; } }
|
||||
|
||||
protected override DrawOp GetDrawOp(DrawArgs dArgs) {
|
||||
Player p = dArgs.Player;
|
||||
if (dArgs.Message.Length == 0) { Help(p); return null; }
|
||||
|
||||
Write2DrawOp op = new Write2DrawOp();
|
||||
op.Text = dArgs.Message.ToUpper();
|
||||
return op;
|
||||
}
|
||||
|
||||
protected override void GetMarks(DrawArgs dArgs, ref Vec3S32[] m) {
|
||||
if (m[0].X != m[1].X || m[0].Z != m[1].Z) return;
|
||||
Player.Message(dArgs.Player, "No direction was selected");
|
||||
m = null;
|
||||
}
|
||||
|
||||
public override void Help(Player p) {
|
||||
Player.Message(p, "%T/Write2 [message]");
|
||||
Player.Message(p, "%HWrites [message] in letter blocks");
|
||||
}
|
||||
}
|
||||
}
|
@ -44,8 +44,8 @@ namespace MCGalaxy.SQL {
|
||||
|
||||
|
||||
public override void CreateDatabase() {
|
||||
ParameterisedQuery query = GetStaticParameterised();
|
||||
Database.Execute(query, "CREATE DATABASE if not exists `" + ServerConfig.MySQLDatabaseName + "`", true);
|
||||
string syntax = "CREATE DATABASE if not exists `" + ServerConfig.MySQLDatabaseName + "`";
|
||||
Database.Do(syntax, true, null, null, null);
|
||||
}
|
||||
|
||||
public override BulkTransaction CreateBulk() {
|
||||
@ -58,8 +58,8 @@ namespace MCGalaxy.SQL {
|
||||
|
||||
protected internal override ParameterisedQuery GetStaticParameterised() {
|
||||
return queryInstance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override string FastGetDateTime(IDataRecord record, int col) {
|
||||
DateTime date = record.GetDateTime(col);
|
||||
return date.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
@ -86,34 +86,21 @@ namespace MCGalaxy.SQL {
|
||||
cmd = cmd.Insert(cmd.LastIndexOf(")"), ", PRIMARY KEY (`" + name + "`)");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static object IterateExists(IDataRecord record, object arg) { return ""; }
|
||||
public override bool TableExists(string table) {
|
||||
ValidateTable(table);
|
||||
const string syntax = "SELECT * FROM information_schema.tables WHERE table_name = @0 AND table_schema = @1";
|
||||
using (DataTable results = Database.Fill(syntax, table, ServerConfig.MySQLDatabaseName)) {
|
||||
return results.Rows.Count > 0;
|
||||
}
|
||||
return Database.Iterate("SHOW TABLES LIKE '" + table + "'",
|
||||
null, IterateExists) != null;
|
||||
}
|
||||
|
||||
public override List<string> AllTables() {
|
||||
using (DataTable results = Database.Fill("SHOW TABLES")) {
|
||||
List<string> tables = new List<string>(results.Rows.Count);
|
||||
foreach (DataRow row in results.Rows) {
|
||||
tables.Add(row[0].ToString());
|
||||
}
|
||||
return tables;
|
||||
}
|
||||
return Database.GetStrings("SHOW TABLES");
|
||||
}
|
||||
|
||||
public override List<string> ColumnNames(string table) {
|
||||
ValidateTable(table);
|
||||
using (DataTable results = Database.Fill("DESCRIBE `" + table + "`")) {
|
||||
List<string> columns = new List<string>(results.Rows.Count);
|
||||
foreach (DataRow row in results.Rows) {
|
||||
columns.Add(row["Field"].ToString());
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
return Database.GetStrings("DESCRIBE `" + table + "`");
|
||||
}
|
||||
|
||||
public override void RenameTable(string srcTable, string dstTable) {
|
||||
@ -127,7 +114,7 @@ namespace MCGalaxy.SQL {
|
||||
ValidateTable(table);
|
||||
string syntax = "TRUNCATE TABLE `" + table + "`";
|
||||
Database.Execute(syntax);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CreateTableColumns(StringBuilder sql, ColumnDesc[] columns) {
|
||||
string priKey = null;
|
||||
@ -146,36 +133,41 @@ namespace MCGalaxy.SQL {
|
||||
}
|
||||
sql.AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static object IterateFields(IDataRecord record, object arg) {
|
||||
string[] field = new string[record.FieldCount];
|
||||
for (int i = 0; i < field.Length; i++) { field[i] = record.GetString(i); }
|
||||
|
||||
((List<string[]>)arg).Add(field);
|
||||
return arg;
|
||||
}
|
||||
|
||||
public override void PrintSchema(string table, TextWriter w) {
|
||||
string pri = "";
|
||||
w.WriteLine("CREATE TABLE IF NOT EXISTS `{0}` (", table);
|
||||
List<string[]> fields = new List<string[]>();
|
||||
Database.Iterate("DESCRIBE `" + table + "`", fields, IterateFields);
|
||||
|
||||
using (DataTable schema = Database.Fill("DESCRIBE `" + table + "`")) {
|
||||
string[] data = new string[schema.Columns.Count];
|
||||
foreach (DataRow row in schema.Rows) {
|
||||
for (int col = 0; col < schema.Columns.Count; col++) {
|
||||
data[col] = row[col].ToString();
|
||||
}
|
||||
|
||||
if (data[3].CaselessEq("pri")) pri = data[0];
|
||||
string value = data[2].CaselessEq("no") ? "NOT NULL" : "DEFAULT NULL";
|
||||
if (data[4].Length > 0) value += " DEFAULT '" + data[4] + "'";
|
||||
if (data[5].Length > 0) value += " " + data[5];
|
||||
string pri = "";
|
||||
for (int i = 0; i < fields.Count; i++) {
|
||||
string[] field = fields[i];
|
||||
|
||||
if (field[3].CaselessEq("pri")) pri = field[0];
|
||||
string value = field[2].CaselessEq("no") ? "NOT NULL" : "DEFAULT NULL";
|
||||
if (field[4].Length > 0) value += " DEFAULT '" + field[4] + "'";
|
||||
if (field[5].Length > 0) value += " " + field[5];
|
||||
|
||||
string suffix = pri.Length == 0 && row == schema.Rows[schema.Rows.Count - 1] ? "" : ",";
|
||||
w.WriteLine("`{0}` {1} {2}{3}", row[0], row[1], value, suffix);
|
||||
}
|
||||
string suffix = pri.Length == 0 && (i == fields.Count - 1) ? "" : ",";
|
||||
w.WriteLine("`{0}` {1} {2}{3}", field[0], field[1], value, suffix);
|
||||
}
|
||||
|
||||
if (pri.Length > 0) w.Write("PRIMARY KEY (`{0}`)", pri);
|
||||
w.WriteLine(");");
|
||||
}
|
||||
|
||||
|
||||
public override void AddColumn(string table, ColumnDesc col, string colAfter) {
|
||||
ValidateTable(table);
|
||||
string syntax = "ALTER TABLE `" + table + "` ADD COLUMN "
|
||||
string syntax = "ALTER TABLE `" + table + "` ADD COLUMN "
|
||||
+ col.Column + " " + col.FormatType();
|
||||
if (colAfter.Length > 0) syntax += " AFTER " + colAfter;
|
||||
Database.Execute(syntax);
|
||||
@ -227,5 +219,5 @@ namespace MCGalaxy.SQL {
|
||||
protected override IDbDataParameter CreateParameter() {
|
||||
return new MySqlParameter();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace MCGalaxy.SQL {
|
||||
public static IDatabaseBackend Instance = new SQLiteBackend();
|
||||
static ParameterisedQuery queryInstance = new SQLiteParameterisedQuery();
|
||||
|
||||
static string connFormat = "Data Source =" + Utils.FolderPath + "/MCGalaxy.db; Version =3; Pooling ={0}; Max Pool Size =300;";
|
||||
static string connFormat = "Data Source =" + Utils.FolderPath + "/MCGalaxy.db; Version =3; Pooling ={0}; Max Pool Size =300;";
|
||||
public override string ConnectionString {
|
||||
get { return string.Format(connFormat, ServerConfig.DatabasePooling); }
|
||||
}
|
||||
@ -60,35 +60,36 @@ namespace MCGalaxy.SQL {
|
||||
return record.GetString(col); // reader.GetDateTime is extremely slow so avoid it
|
||||
}
|
||||
|
||||
|
||||
public override bool TableExists(string table) {
|
||||
ValidateTable(table);
|
||||
using (DataTable results = GetRows("sqlite_master", "name",
|
||||
"WHERE type='table' AND name=@0", table)) {
|
||||
return results.Rows.Count > 0;
|
||||
}
|
||||
return Database.CountRows("sqlite_master",
|
||||
"WHERE type='table' AND name=@0", table) > 0;
|
||||
}
|
||||
|
||||
public override List<string> AllTables() {
|
||||
using (DataTable results = GetRows("sqlite_master", "name", "WHERE type='table'")) {
|
||||
List<string> tables = new List<string>(results.Rows.Count);
|
||||
foreach (DataRow row in results.Rows) {
|
||||
if (row["name"].ToString().StartsWith("sqlite_")) continue;
|
||||
tables.Add(row["name"].ToString());
|
||||
}
|
||||
return tables;
|
||||
const string syntax = "SELECT name from sqlite_master WHERE type='table'";
|
||||
List<string> tables = Database.GetStrings(syntax);
|
||||
|
||||
// exclude sqlite built-in database tables
|
||||
for (int i = tables.Count - 1; i >= 0; i--) {
|
||||
if (tables[i].StartsWith("sqlite_")) tables.RemoveAt(i);
|
||||
}
|
||||
return tables;
|
||||
}
|
||||
|
||||
static object IterateColumnNames(IDataRecord record, object arg) {
|
||||
List<string> columns = (List<string>)arg;
|
||||
columns.Add(record.GetString("name"));
|
||||
return arg;
|
||||
}
|
||||
|
||||
public override List<string> ColumnNames(string table) {
|
||||
ValidateTable(table);
|
||||
using (DataTable results = Database.Fill("PRAGMA table_info(`" + table + "`)")) {
|
||||
List<string> columns = new List<string>(results.Rows.Count);
|
||||
foreach (DataRow row in results.Rows) {
|
||||
columns.Add(row["name"].ToString());
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
List<string> columns = new List<string>();
|
||||
|
||||
Database.Iterate("PRAGMA table_info(`" + table + "`)",
|
||||
columns, IterateColumnNames);
|
||||
return columns;
|
||||
}
|
||||
|
||||
public override void RenameTable(string srcTable, string dstTable) {
|
||||
@ -105,7 +106,7 @@ namespace MCGalaxy.SQL {
|
||||
}
|
||||
|
||||
protected override void CreateTableColumns(StringBuilder sql, ColumnDesc[] columns) {
|
||||
string priKey = null;
|
||||
string priKey = null;
|
||||
for (int i = 0; i < columns.Length; i++) {
|
||||
ColumnDesc col = columns[i];
|
||||
sql.Append(col.Column).Append(' ');
|
||||
@ -135,21 +136,20 @@ namespace MCGalaxy.SQL {
|
||||
}
|
||||
|
||||
public override void PrintSchema(string table, TextWriter w) {
|
||||
const string syntax = "SELECT sql FROM sqlite_master WHERE tbl_name = @0 AND type = 'table'";
|
||||
using (DataTable schema = Database.Fill(syntax + CaselessWhereSuffix, table)) {
|
||||
foreach (DataRow row in schema.Rows) {
|
||||
string sql = row[0].ToString();
|
||||
sql = sql.Replace(" " + table, " `" + table + "`");
|
||||
sql = sql.Replace("CREATE TABLE `" + table + "`", "CREATE TABLE IF NOT EXISTS `" + table + "`");
|
||||
w.WriteLine(sql + ";");
|
||||
}
|
||||
const string syntax = "SELECT sql from sqlite_master WHERE tbl_name = @0 AND type = 'table'";
|
||||
List<string> all = Database.GetStrings(syntax + CaselessWhereSuffix, table);
|
||||
|
||||
for (int i = 0; i < all.Count; i++) {
|
||||
string sql = all[i];
|
||||
sql = sql.Replace(" " + table, " `" + table + "`");
|
||||
sql = sql.Replace("CREATE TABLE `" + table + "`", "CREATE TABLE IF NOT EXISTS `" + table + "`");
|
||||
w.WriteLine(sql + ";");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void AddColumn(string table, ColumnDesc col, string colAfter) {
|
||||
ValidateTable(table);
|
||||
string syntax = "ALTER TABLE `" + table + "` ADD COLUMN "
|
||||
+ col.Column + " " + col.FormatType();
|
||||
string syntax = "ALTER TABLE `" + table + "` ADD COLUMN " + col.Column + " " + col.FormatType();
|
||||
Database.Execute(syntax);
|
||||
}
|
||||
|
||||
@ -160,9 +160,9 @@ namespace MCGalaxy.SQL {
|
||||
}
|
||||
|
||||
|
||||
public sealed class SQLiteBulkTransaction : BulkTransaction {
|
||||
public sealed class SQLiteBulkTransaction : BulkTransaction {
|
||||
|
||||
public SQLiteBulkTransaction(string connString) {
|
||||
public SQLiteBulkTransaction(string connString) {
|
||||
connection = new SQLiteConnection(connString);
|
||||
connection.Open();
|
||||
transaction = connection.BeginTransaction();
|
||||
@ -177,7 +177,7 @@ namespace MCGalaxy.SQL {
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SQLiteParameterisedQuery : ParameterisedQuery {
|
||||
public sealed class SQLiteParameterisedQuery : ParameterisedQuery {
|
||||
protected override bool MultipleSchema { get { return false; } }
|
||||
|
||||
protected override IDbConnection CreateConnection(string connString) {
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
using System;
|
||||
using System.Data;
|
||||
using MCGalaxy.Blocks.Extended;
|
||||
using MCGalaxy.SQL;
|
||||
using BlockID = System.UInt16;
|
||||
|
||||
@ -26,7 +27,7 @@ namespace MCGalaxy.DB {
|
||||
public static class BlockDBChange {
|
||||
|
||||
public static void Output(Player p, string name, BlockDBEntry e) {
|
||||
BlockID oldBlock = e.OldBlock, newBlock = e.NewBlock;
|
||||
BlockID oldBlock = e.OldBlock, newBlock = e.NewBlock;
|
||||
DateTime time = BlockDB.Epoch.AddSeconds(e.TimeDelta);
|
||||
TimeSpan delta = DateTime.UtcNow.Subtract(time);
|
||||
name = PlayerInfo.GetColoredName(p, name);
|
||||
@ -46,43 +47,21 @@ namespace MCGalaxy.DB {
|
||||
|
||||
public static void OutputMessageBlock(Player p, BlockID block, ushort x, ushort y, ushort z) {
|
||||
if (!p.level.Props[block].IsMessageBlock) return;
|
||||
|
||||
try {
|
||||
if (!Database.TableExists("Messages" + p.level.name)) return;
|
||||
DataTable messages = Database.Backend.GetRows("Messages" + p.level.name, "*",
|
||||
"WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z);
|
||||
int last = messages.Rows.Count - 1;
|
||||
if (last == -1) { messages.Dispose(); return; }
|
||||
|
||||
string message = messages.Rows[last]["Message"].ToString().Trim();
|
||||
message = message.Replace("\\'", "\'");
|
||||
Player.Message(p, "Message Block contents: {0}", message);
|
||||
} catch {
|
||||
}
|
||||
string message = MessageBlock.Get(p.level.MapName, x, y, z);
|
||||
|
||||
if (message == null) return;
|
||||
Player.Message(p, "Message Block contents: {0}", message);
|
||||
}
|
||||
|
||||
public static void OutputPortal(Player p, BlockID block, ushort x, ushort y, ushort z) {
|
||||
if (!p.level.Props[block].IsPortal) return;
|
||||
|
||||
try {
|
||||
if (!Database.TableExists("Portals" + p.level.name)) return;
|
||||
DataTable portals = Database.Backend.GetRows("Portals" + p.level.name, "*",
|
||||
"WHERE EntryX=@0 AND EntryY=@1 AND EntryZ=@2", x, y, z);
|
||||
int last = portals.Rows.Count - 1;
|
||||
if (last == -1) { portals.Dispose(); return; }
|
||||
|
||||
string exitMap = portals.Rows[last]["ExitMap"].ToString().Trim();
|
||||
ushort exitX = U16(portals.Rows[last]["ExitX"]);
|
||||
ushort exitY = U16(portals.Rows[last]["ExitY"]);
|
||||
ushort exitZ = U16(portals.Rows[last]["ExitZ"]);
|
||||
Player.Message(p, "Portal destination: ({0}, {1}, {2}) in {3}",
|
||||
exitX, exitY, exitZ, exitMap);
|
||||
} catch {
|
||||
}
|
||||
Portal.PortalExitData exit = Portal.Get(p.level.MapName, x, y, z);
|
||||
|
||||
if (exit == null) return;
|
||||
Player.Message(p, "Portal destination: ({0}, {1}, {2}) in {3}",
|
||||
exit.X, exit.Y, exit.Z, exit.Map);
|
||||
}
|
||||
|
||||
static ushort U16(object x) { return ushort.Parse(x.ToString()); }
|
||||
|
||||
static string FormatReason(ushort flags) {
|
||||
if ((flags & BlockDBFlags.Painted) != 0) return " (Painted)";
|
||||
if ((flags & BlockDBFlags.Drawn) != 0) return " (Drawn)";
|
||||
|
@ -45,7 +45,7 @@ namespace MCGalaxy.DB {
|
||||
mapName = table.Substring("Block".Length);
|
||||
|
||||
try {
|
||||
Database.Iterate("SELECT * FROM `" + table + "`", DumpRow);
|
||||
Database.Backend.IterateRows(table, "*", null, DumpRow);
|
||||
WriteBuffer(true);
|
||||
AppendCbdbFile();
|
||||
SaveCbdbFile();
|
||||
@ -58,8 +58,8 @@ namespace MCGalaxy.DB {
|
||||
Database.Backend.DeleteTable(table);
|
||||
}
|
||||
|
||||
bool DumpRow(IDataRecord record) {
|
||||
if (errorOccurred) return false;
|
||||
object DumpRow(IDataRecord record, object arg) {
|
||||
if (errorOccurred) return arg;
|
||||
|
||||
try {
|
||||
if (stream == null) {
|
||||
@ -87,7 +87,7 @@ namespace MCGalaxy.DB {
|
||||
Logger.LogError(ex);
|
||||
errorOccurred = true;
|
||||
}
|
||||
return true;
|
||||
return arg;
|
||||
}
|
||||
|
||||
void WriteBuffer(bool force) {
|
||||
|
@ -33,25 +33,25 @@ namespace MCGalaxy.DB {
|
||||
if (id > MaxPlayerID - invalid.Count)
|
||||
return invalid[MaxPlayerID - id];
|
||||
|
||||
using (DataTable ids = Database.Backend.GetRows("Players", "Name", "WHERE ID=@0", id)) {
|
||||
if (ids.Rows.Count == 0) return "ID#" + id;
|
||||
return ids.Rows[0]["Name"].ToString();
|
||||
}
|
||||
string name = Database.GetString("Players", "Name", "WHERE ID=@0", id);
|
||||
return name != null ? name : "ID#" + id;
|
||||
}
|
||||
|
||||
static object IterateFindIds(IDataRecord record, object arg) {
|
||||
List<int> ids = (List<int>)arg;
|
||||
ids.Add(record.GetInt32(0));
|
||||
return arg;
|
||||
}
|
||||
|
||||
public static int[] FindIds(string name) {
|
||||
List<string> invalid = Server.invalidIds.All();
|
||||
List<int> ids = new List<int>();
|
||||
|
||||
int index = invalid.CaselessIndexOf(name);
|
||||
if (index >= 0) ids.Add(MaxPlayerID - index);
|
||||
int i = invalid.CaselessIndexOf(name);
|
||||
if (i >= 0) ids.Add(MaxPlayerID - i);
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
Database.Backend.IterateRows("Players", "ID", ids, IterateFindIds,
|
||||
"WHERE Name=@0", name);
|
||||
return ids.ToArray();
|
||||
}
|
||||
|
||||
|
@ -16,62 +16,69 @@
|
||||
permissions and limitations under the Licenses.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
|
||||
namespace MCGalaxy.SQL {
|
||||
/// <summary> Callback function invoked on a row returned from an SQL query. </summary>
|
||||
public delegate object ReaderCallback(IDataRecord record, object arg);
|
||||
|
||||
public static class Database {
|
||||
|
||||
public static IDatabaseBackend Backend;
|
||||
|
||||
/// <summary> Returns whether the given table exists in the database. </summary>
|
||||
public static bool TableExists(string table) { return Backend.TableExists(table); }
|
||||
|
||||
|
||||
/// <summary> Executes an SQL command that does not return any results. </summary>
|
||||
public static void Execute(string sql) {
|
||||
ParameterisedQuery query = Backend.GetStaticParameterised();
|
||||
Execute(query, sql, false, null);
|
||||
static object IterateCount(IDataRecord record, object arg) { return record.GetInt32(0); }
|
||||
public static int CountRows(string table, string modifier = "", params object[] args) {
|
||||
return (int)Backend.IterateRows(table, "COUNT(*)", 0,
|
||||
IterateCount, modifier, args);
|
||||
}
|
||||
|
||||
|
||||
static object IterateString(IDataRecord record, object arg) { return record.GetString(0); }
|
||||
public static string GetString(string table, string column,
|
||||
string modifier = "", params object[] args) {
|
||||
return (string)Backend.IterateRows(table, column, null,
|
||||
IterateString, modifier, args);
|
||||
}
|
||||
|
||||
|
||||
static object IterateList(IDataRecord record, object arg) {
|
||||
((List<string>)arg).Add(record.GetString(0)); return arg;
|
||||
}
|
||||
internal static List<string> GetStrings(string sql, params object[] args) {
|
||||
List<string> values = new List<string>();
|
||||
Iterate(sql, values, IterateList, args);
|
||||
return values;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Executes an SQL command that does not return any results. </summary>
|
||||
public static void Execute(string sql, params object[] args) {
|
||||
ParameterisedQuery query = Backend.CreateParameterised();
|
||||
Execute(query, sql, false, args);
|
||||
Do(sql, false, null, null, null, args);
|
||||
}
|
||||
|
||||
/// <summary> Executes an SQL query, invoking callback function on each returned row. </summary>
|
||||
public static void Iterate(string sql, ReaderCallback callback, params object[] args) {
|
||||
ParameterisedQuery query = Backend.CreateParameterised();
|
||||
DoDatabaseCall(query, sql, false, null, callback, args);
|
||||
public static object Iterate(string sql, object arg, ReaderCallback callback, params object[] args) {
|
||||
return Do(sql, false, arg, null, callback, args);
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Executes an SQL query, returning all read rows into a DataTable. </summary>
|
||||
public static DataTable Fill(string sql) {
|
||||
ParameterisedQuery query = Backend.GetStaticParameterised();
|
||||
return Fill(query, sql, null);
|
||||
}
|
||||
|
||||
/// <summary> Executes an SQL query, returning all read rows into a DataTable. </summary>
|
||||
public static DataTable Fill(string sql, params object[] args) {
|
||||
ParameterisedQuery query = Backend.CreateParameterised();
|
||||
return Fill(query, sql, args);
|
||||
}
|
||||
|
||||
|
||||
internal static void Execute(ParameterisedQuery query, string sql, bool createDB, params object[] args) {
|
||||
DoDatabaseCall(query, sql, createDB, null, null, args);
|
||||
}
|
||||
|
||||
internal static DataTable Fill(ParameterisedQuery query, string sql, params object[] args) {
|
||||
using (DataTable results = new DataTable("toReturn")) {
|
||||
DoDatabaseCall(query, sql, false, results, null, args);
|
||||
using (DataTable results = new DataTable("toReturn")) {
|
||||
Do(sql, false, null, results, null, args);
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
static void DoDatabaseCall(ParameterisedQuery query, string sql, bool createDB,
|
||||
DataTable results, ReaderCallback callback, params object[] args) {
|
||||
internal static object Do(string sql, bool createDB, object arg,
|
||||
DataTable results, ReaderCallback callback, params object[] args) {
|
||||
ParameterisedQuery query;
|
||||
if (args == null || args.Length == 0) {
|
||||
query = Backend.GetStaticParameterised();
|
||||
} else {
|
||||
query = Backend.CreateParameterised();
|
||||
}
|
||||
|
||||
query.parameters = args;
|
||||
string connString = Backend.ConnectionString;
|
||||
Exception e = null;
|
||||
@ -79,7 +86,7 @@ namespace MCGalaxy.SQL {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
try {
|
||||
if (callback != null) {
|
||||
query.Iterate(sql, connString, callback);
|
||||
arg = query.Iterate(sql, connString, arg, callback);
|
||||
} else if (results == null) {
|
||||
query.Execute(sql, connString, createDB);
|
||||
} else {
|
||||
@ -87,7 +94,7 @@ namespace MCGalaxy.SQL {
|
||||
}
|
||||
|
||||
query.parameters = null;
|
||||
return;
|
||||
return arg;
|
||||
} catch (Exception ex) {
|
||||
e = ex; // try yet again
|
||||
}
|
||||
@ -96,6 +103,7 @@ namespace MCGalaxy.SQL {
|
||||
query.parameters = null;
|
||||
File.AppendAllText("MySQL_error.log", DateTime.Now + " " + sql + "\r\n");
|
||||
Logger.LogError(e);
|
||||
return arg;
|
||||
}
|
||||
|
||||
|
||||
@ -110,5 +118,22 @@ namespace MCGalaxy.SQL {
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
internal static string GetString(this IDataRecord record, string name) {
|
||||
return record.GetString(record.GetOrdinal(name));
|
||||
}
|
||||
|
||||
internal static int GetInt32(this IDataRecord record, string name) {
|
||||
return record.GetInt32(record.GetOrdinal(name));
|
||||
}
|
||||
|
||||
internal static long GetInt64(this IDataRecord record, string name) {
|
||||
return record.GetInt64(record.GetOrdinal(name));
|
||||
}
|
||||
|
||||
internal static DateTime GetDateTime(this IDataRecord record, string name) {
|
||||
string raw = Database.Backend.FastGetDateTime(record, record.GetOrdinal(name));
|
||||
return DateTime.ParseExact(raw, "yyyy-MM-dd HH:mm:ss", null);
|
||||
}
|
||||
}
|
||||
}
|
@ -55,7 +55,7 @@ namespace MCGalaxy.SQL {
|
||||
/// for sql queries with no parameters. </summary>
|
||||
protected internal abstract ParameterisedQuery GetStaticParameterised();
|
||||
|
||||
public abstract string FastGetDateTime(IDataRecord reader, int col);
|
||||
public abstract string FastGetDateTime(IDataRecord record, int col);
|
||||
|
||||
protected internal virtual void ParseCreate(ref string cmd) { }
|
||||
|
||||
@ -129,6 +129,17 @@ namespace MCGalaxy.SQL {
|
||||
return Database.Fill(syntax, args);
|
||||
}
|
||||
|
||||
/// <summary> Iterates over read rows for the given table. </summary>
|
||||
/// <remarks> modifier is optional SQL which can be used to retrieve only certain rows,
|
||||
/// return rows in a certain order, etc.</remarks>
|
||||
public virtual object IterateRows(string table, string columns, object arg,
|
||||
ReaderCallback callback, string modifier = "", params object[] args) {
|
||||
ValidateTable(table);
|
||||
string syntax = "SELECT " + columns + " FROM `" + table + "`";
|
||||
if (modifier.Length > 0) syntax += " " + modifier;
|
||||
return Database.Iterate(syntax, arg, callback, args);
|
||||
}
|
||||
|
||||
/// <summary> Updates rows for the given table. </summary>
|
||||
/// <remarks> modifier is optional SQL which can be used to update only certain rows.</remarks>
|
||||
public virtual void UpdateRows(string table, string columns,
|
||||
|
@ -21,9 +21,6 @@ using System.Data;
|
||||
using System.Data.Common;
|
||||
|
||||
namespace MCGalaxy.SQL {
|
||||
|
||||
/// <summary> Callback function invoked on a row returned from an SQL query. </summary>
|
||||
public delegate bool ReaderCallback(IDataRecord record);
|
||||
|
||||
/// <summary> Represents an SQL command or query, that takes named parameters/arguments. </summary>
|
||||
public abstract class ParameterisedQuery {
|
||||
@ -69,7 +66,7 @@ namespace MCGalaxy.SQL {
|
||||
}
|
||||
|
||||
/// <summary> Excecutes an SQL query, invoking a callback on the returned rows one by one. </summary>
|
||||
public void Iterate(string query, string connString, ReaderCallback callback) {
|
||||
public object Iterate(string query, string connString, object arg, ReaderCallback callback) {
|
||||
using (IDbConnection conn = CreateConnection(connString)) {
|
||||
conn.Open();
|
||||
if (MultipleSchema)
|
||||
@ -78,11 +75,12 @@ namespace MCGalaxy.SQL {
|
||||
using (IDbCommand cmd = CreateCommand(query, conn)) {
|
||||
FillParams(cmd);
|
||||
using (IDataReader reader = cmd.ExecuteReader()) {
|
||||
while (reader.Read() && callback(reader)) { }
|
||||
while (reader.Read()) { arg = callback(reader, arg); }
|
||||
}
|
||||
}
|
||||
conn.Close();
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
void FillParams(IDbCommand cmd) {
|
||||
|
@ -23,8 +23,7 @@ namespace MCGalaxy.DB {
|
||||
|
||||
/// <summary> Retrieves or sets player stats in the database. </summary>
|
||||
public class PlayerData {
|
||||
|
||||
public const string DBTable = "Players";
|
||||
|
||||
public const string ColumnDeaths = "totalDeaths";
|
||||
public const string ColumnLogins = "totalLogin";
|
||||
public const string ColumnMoney = "Money";
|
||||
@ -50,16 +49,16 @@ namespace MCGalaxy.DB {
|
||||
|
||||
internal static void Create(Player p) {
|
||||
p.prefix = "";
|
||||
p.color = p.group.Color;
|
||||
p.color = p.group.Color;
|
||||
p.FirstLogin = DateTime.Now;
|
||||
p.TimesVisited = 1;
|
||||
|
||||
string now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
Database.Backend.AddRow(DBTable, "Name, IP, FirstLogin, LastLogin, totalLogin, Title, " +
|
||||
string now = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||||
Database.Backend.AddRow("Players", "Name, IP, FirstLogin, LastLogin, totalLogin, Title, " +
|
||||
"totalDeaths, Money, totalBlocks, totalKicked, Messages, TimeSpent",
|
||||
p.name, p.ip, now, now, 1, "", 0, 0, 0, 0, 0, (long)p.TotalTime.TotalSeconds);
|
||||
|
||||
using (DataTable ids = Database.Backend.GetRows(DBTable,
|
||||
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();
|
||||
@ -70,8 +69,7 @@ namespace MCGalaxy.DB {
|
||||
}
|
||||
}
|
||||
|
||||
internal static void Load(DataTable playerDb, Player p) {
|
||||
PlayerData data = PlayerData.Fill(playerDb.Rows[0]);
|
||||
internal static void Apply(PlayerData data, Player p) {
|
||||
p.TimesVisited = data.Logins + 1;
|
||||
p.TotalTime = data.TotalTime;
|
||||
p.DatabaseID = data.DatabaseID;
|
||||
@ -81,7 +79,7 @@ namespace MCGalaxy.DB {
|
||||
p.titlecolor = data.TitleColor;
|
||||
p.color = data.Color;
|
||||
if (p.color.Length == 0) p.color = p.group.Color;
|
||||
|
||||
|
||||
p.TotalModified = data.TotalModified;
|
||||
p.TotalDrawn = data.TotalDrawn;
|
||||
p.TotalPlaced = data.TotalPlaced;
|
||||
@ -93,35 +91,37 @@ namespace MCGalaxy.DB {
|
||||
p.TimesBeenKicked = data.Kicks;
|
||||
}
|
||||
|
||||
public static PlayerData Fill(DataRow row) {
|
||||
internal static object IteratePlayerData(IDataRecord record, object arg) {
|
||||
PlayerData data = new PlayerData();
|
||||
data.Name = row["Name"].ToString().Trim();
|
||||
data.IP = row["IP"].ToString().Trim();
|
||||
data.DatabaseID = ParseInt(row["ID"].ToString());
|
||||
data.Name = record.GetString("Name");
|
||||
data.IP = record.GetString("IP");
|
||||
data.DatabaseID = record.GetInt32("ID");
|
||||
|
||||
// Backwards compatibility with old format
|
||||
string rawTime = record.GetString(ColumnTimeSpent);
|
||||
try {
|
||||
long secs = PlayerData.ParseLong(row[ColumnTimeSpent].ToString());
|
||||
long secs = long.Parse(rawTime);
|
||||
data.TotalTime = TimeSpan.FromSeconds(secs);
|
||||
} catch {
|
||||
data.TotalTime = row[ColumnTimeSpent].ToString().ParseDBTime();
|
||||
data.TotalTime = rawTime.ParseDBTime();
|
||||
}
|
||||
|
||||
data.FirstLogin = ParseDate(row[ColumnFirstLogin]);
|
||||
data.LastLogin = ParseDate(row[ColumnLastLogin]);
|
||||
data.FirstLogin = record.GetDateTime(ColumnFirstLogin);
|
||||
data.LastLogin = record.GetDateTime(ColumnLastLogin);
|
||||
|
||||
data.Title = row[ColumnTitle].ToString().Trim();
|
||||
data.Title = record.GetString(ColumnTitle);
|
||||
data.Title = data.Title.Cp437ToUnicode();
|
||||
data.TitleColor = ParseColor(row[ColumnTColor]);
|
||||
data.Color = ParseColor(row[ColumnColor]);
|
||||
data.TitleColor = ParseCol(record.GetString(ColumnTColor));
|
||||
data.Color = ParseCol(record.GetString(ColumnColor));
|
||||
|
||||
data.Money = ParseInt(row[ColumnMoney].ToString());
|
||||
data.Deaths = ParseInt(row[ColumnDeaths].ToString());
|
||||
data.Logins = ParseInt(row[ColumnLogins].ToString());
|
||||
data.Kicks = ParseInt(row[ColumnKicked].ToString());
|
||||
data.Messages = ParseInt(row[ColumnMessages].ToString());
|
||||
data.Money = record.GetInt32(ColumnMoney);
|
||||
data.Deaths = record.GetInt32(ColumnDeaths);
|
||||
data.Logins = record.GetInt32(ColumnLogins);
|
||||
data.Kicks = record.GetInt32(ColumnKicked);
|
||||
data.Messages = record.GetInt32(ColumnMessages);
|
||||
|
||||
long blocks = ParseLong(row[ColumnTotalBlocks].ToString());
|
||||
long cuboided = ParseLong(row[ColumnTotalCuboided].ToString());
|
||||
long blocks = record.GetInt64(ColumnTotalBlocks);
|
||||
long cuboided = record.GetInt64(ColumnTotalCuboided);
|
||||
data.TotalModified = blocks & LowerBitsMask;
|
||||
data.TotalPlaced = blocks >> LowerBits;
|
||||
data.TotalDrawn = cuboided & LowerBitsMask;
|
||||
@ -142,14 +142,13 @@ namespace MCGalaxy.DB {
|
||||
return (value.Length == 0 || value.CaselessEq("null")) ? 0 : int.Parse(value);
|
||||
}
|
||||
|
||||
static string ParseColor(object value) {
|
||||
string col = value.ToString().Trim();
|
||||
if (col.Length == 0) return col;
|
||||
static string ParseCol(string raw) {
|
||||
if (raw.Length == 0) return raw;
|
||||
|
||||
// Try parse color name, then color code
|
||||
string parsed = Colors.Parse(col);
|
||||
if (parsed.Length > 0) return parsed;
|
||||
return Colors.Name(col).Length == 0 ? "" : col;
|
||||
string col = Colors.Parse(raw);
|
||||
if (col.Length > 0) return col;
|
||||
return Colors.Name(raw).Length == 0 ? "" : raw;
|
||||
}
|
||||
|
||||
|
||||
@ -165,15 +164,15 @@ namespace MCGalaxy.DB {
|
||||
public const long LowerBitsMask = (1L << LowerBits) - 1;
|
||||
|
||||
|
||||
static bool IterateFindCol(IDataRecord record, object arg) {
|
||||
arg = record.GetString(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string FindDBColor(Player p) {
|
||||
using (DataTable colors = Database.Backend.GetRows(DBTable,
|
||||
"Color", "WHERE ID = @0", p.DatabaseID)) {
|
||||
if (colors.Rows.Count > 0) {
|
||||
string col = ParseColor(colors.Rows[0]["Color"]);
|
||||
if (col.Length > 0) return col;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
string raw = Database.GetString("Players", "Color", "WHERE ID=@0", p.DatabaseID);
|
||||
if (raw == null) return "";
|
||||
return ParseCol(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,38 +51,38 @@ namespace MCGalaxy.DB {
|
||||
|
||||
/// <summary> List of stats that can be ordered. </summary>
|
||||
public static List<TopStat> Stats = new List<TopStat>() {
|
||||
new TopStat("Logins", PlayerData.DBTable,
|
||||
new TopStat("Logins", "Players",
|
||||
PlayerData.ColumnLogins, MostLogins, FormatInteger),
|
||||
new TopStat("Deaths", PlayerData.DBTable,
|
||||
new TopStat("Deaths", "Players",
|
||||
PlayerData.ColumnDeaths, MostDeaths, FormatInteger),
|
||||
new TopStat("Money", PlayerData.DBTable,
|
||||
new TopStat("Money", "Players",
|
||||
PlayerData.ColumnMoney, MostMoney, FormatInteger),
|
||||
new TopStat("Oldest", PlayerData.DBTable,
|
||||
new TopStat("Oldest", "Players",
|
||||
PlayerData.ColumnFirstLogin, MostOldest, FormatDate, true),
|
||||
new TopStat("Newest", PlayerData.DBTable,
|
||||
new TopStat("Newest", "Players",
|
||||
PlayerData.ColumnFirstLogin, MostNewest, FormatDate),
|
||||
new TopStat("Recent", PlayerData.DBTable,
|
||||
new TopStat("Recent", "Players",
|
||||
PlayerData.ColumnLastLogin, MostRecent, FormatDate),
|
||||
new TopStat("Least-Recent", PlayerData.DBTable,
|
||||
new TopStat("Least-Recent", "Players",
|
||||
PlayerData.ColumnLastLogin, MostNotRecent, FormatDate, true),
|
||||
new TopStat("Kicked", PlayerData.DBTable,
|
||||
new TopStat("Kicked", "Players",
|
||||
PlayerData.ColumnKicked, MostKicked, FormatInteger),
|
||||
new TopStat("Modified", PlayerData.DBTable,
|
||||
new TopStat("Modified", "Players",
|
||||
PlayerData.ColumnTotalBlocks + " & " + PlayerData.LowerBitsMask,
|
||||
MostModified, FormatInteger),
|
||||
new TopStat("Drawn", PlayerData.DBTable,
|
||||
new TopStat("Drawn", "Players",
|
||||
PlayerData.ColumnTotalCuboided + " & " + PlayerData.LowerBitsMask,
|
||||
MostDrawn, FormatInteger),
|
||||
new TopStat("Placed", PlayerData.DBTable,
|
||||
new TopStat("Placed", "Players",
|
||||
PlayerData.ColumnTotalBlocks + " >> " + PlayerData.LowerBits,
|
||||
MostPlaced, FormatInteger),
|
||||
new TopStat("Deleted", PlayerData.DBTable,
|
||||
new TopStat("Deleted", "Players",
|
||||
PlayerData.ColumnTotalCuboided + " >> " + PlayerData.LowerBits,
|
||||
MostDeleted, FormatInteger),
|
||||
new TopStat("TimeSpent", PlayerData.DBTable,
|
||||
new TopStat("TimeSpent", "Players",
|
||||
PlayerData.ColumnTimeSpent, MostTime, FormatTimespan,
|
||||
false, " CAST(TimeSpent as unsigned) "),
|
||||
new TopStat("Messages", PlayerData.DBTable,
|
||||
new TopStat("Messages", "Players",
|
||||
PlayerData.ColumnMessages, MostMessages, FormatInteger),
|
||||
};
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace MCGalaxy.SQL {
|
||||
gottenRows = false;
|
||||
this.sql = sql;
|
||||
this.table = table;
|
||||
Database.Iterate("SELECT * FROM `" + table + "`", DumpRow);
|
||||
Database.Backend.IterateRows(table, "*", null, DumpRow);
|
||||
|
||||
if (!gottenRows) {
|
||||
sql.WriteLine("-- No data in table `{0}`!", table);
|
||||
@ -55,7 +55,7 @@ namespace MCGalaxy.SQL {
|
||||
gottenRows = true;
|
||||
}
|
||||
|
||||
bool DumpRow(IDataRecord record) {
|
||||
object DumpRow(IDataRecord record, object arg) {
|
||||
if (!gottenRows) MakeInsertFormat(record);
|
||||
sql.WriteLine(insertCols);
|
||||
|
||||
@ -79,7 +79,7 @@ namespace MCGalaxy.SQL {
|
||||
}
|
||||
|
||||
sql.WriteLine();
|
||||
return true;
|
||||
return arg;
|
||||
}
|
||||
|
||||
static string FormatInsertColumns(string[] cols, string name) {
|
||||
|
@ -101,30 +101,26 @@ namespace MCGalaxy.Games {
|
||||
new ColumnDesc("Additional1", ColumnType.Int32),
|
||||
};
|
||||
|
||||
static object IterateStats(IDataRecord record, object arg) {
|
||||
ZombieStats stats;
|
||||
stats.TotalRounds = record.GetInt32("TotalRounds");
|
||||
stats.MaxRounds = record.GetInt32("MaxRounds");
|
||||
stats.TotalInfected = record.GetInt32("TotalInfected");
|
||||
stats.MaxInfected = record.GetInt32("MaxInfected");
|
||||
return stats;
|
||||
}
|
||||
|
||||
static ZombieStats LoadStats(string name) {
|
||||
DataTable table = Database.Backend.GetRows("ZombieStats", "*", "WHERE Name=@0", name);
|
||||
ZombieStats stats = default(ZombieStats);
|
||||
|
||||
if (table.Rows.Count > 0) {
|
||||
DataRow row = table.Rows[0];
|
||||
stats.TotalRounds = PlayerData.ParseInt(row["TotalRounds"].ToString());
|
||||
stats.MaxRounds = PlayerData.ParseInt(row["MaxRounds"].ToString());
|
||||
stats.TotalInfected = PlayerData.ParseInt(row["TotalInfected"].ToString());
|
||||
stats.MaxInfected = PlayerData.ParseInt(row["MaxInfected"].ToString());
|
||||
}
|
||||
table.Dispose();
|
||||
return stats;
|
||||
ZombieStats stats = default(ZombieStats);
|
||||
return (ZombieStats)Database.Backend.IterateRows("ZombieStats", "*", stats,
|
||||
IterateStats, "WHERE Name=@0", name);
|
||||
}
|
||||
|
||||
static void SaveStats(Player p) {
|
||||
ZSData data = TryGet(p);
|
||||
if (data == null || data.TotalRoundsSurvived == 0 && data.TotalInfected == 0) return;
|
||||
|
||||
int count = 0;
|
||||
using (DataTable table = Database.Backend.GetRows("ZombieStats", "*", "WHERE Name=@0", p.name)) {
|
||||
count = table.Rows.Count;
|
||||
}
|
||||
|
||||
int count = Database.CountRows("ZombieStats", "WHERE Name=@0", p.name);
|
||||
if (count == 0) {
|
||||
Database.Backend.AddRow("ZombieStats", "TotalRounds, MaxRounds, TotalInfected, MaxInfected, Name",
|
||||
data.TotalRoundsSurvived, data.MaxRoundsSurvived,
|
||||
|
@ -18,6 +18,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using MCGalaxy.Blocks.Extended;
|
||||
using MCGalaxy.Maths;
|
||||
using MCGalaxy.SQL;
|
||||
using MCGalaxy.Util;
|
||||
using BlockID = System.UInt16;
|
||||
@ -64,7 +66,7 @@ namespace MCGalaxy {
|
||||
continue;
|
||||
} else {
|
||||
z.Access.Whitelisted.Add(owner);
|
||||
z.Access.Min = LevelPermission.Admin;
|
||||
z.Access.Min = LevelPermission.Admin;
|
||||
}
|
||||
|
||||
z.Config.Name = "Zone" + id;
|
||||
@ -99,19 +101,13 @@ namespace MCGalaxy {
|
||||
|
||||
internal static void LoadMessages(Level level, string name) {
|
||||
level.hasMessageBlocks = Database.TableExists("Messages" + name);
|
||||
if (!level.hasMessageBlocks) return;
|
||||
if (!level.hasMessageBlocks) return;
|
||||
List<Vec3U16> coords = MessageBlock.GetAll(name);
|
||||
|
||||
using (DataTable table = Database.Backend.GetRows("Messages" + name, "*")) {
|
||||
foreach (DataRow row in table.Rows) {
|
||||
ushort x = ushort.Parse(row["X"].ToString());
|
||||
ushort y = ushort.Parse(row["Y"].ToString());
|
||||
ushort z = ushort.Parse(row["Z"].ToString());
|
||||
|
||||
BlockID block = level.GetBlock(x, y, z);
|
||||
if (level.Props[block].IsMessageBlock) continue;
|
||||
|
||||
Database.Backend.DeleteRows("Messages" + name, "WHERE X=@0 AND Y=@1 AND Z=@2", x, y, z);
|
||||
}
|
||||
foreach (Vec3U16 p in coords) {
|
||||
BlockID block = level.GetBlock(p.X, p.Y, p.Z);
|
||||
if (level.Props[block].IsMessageBlock) continue;
|
||||
MessageBlock.Delete(name, p.X, p.Y, p.Z);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,6 +157,7 @@
|
||||
<Compile Include="Commands\building\CmdSphere.cs" />
|
||||
<Compile Include="Commands\building\CmdTransform.cs" />
|
||||
<Compile Include="Commands\building\CmdTriangle.cs" />
|
||||
<Compile Include="Commands\building\CmdWrite2.cs" />
|
||||
<Compile Include="Commands\building\ReplaceCmds.cs" />
|
||||
<Compile Include="Commands\building\CmdRestartPhysics.cs" />
|
||||
<Compile Include="Commands\building\CmdSpheroid.cs" />
|
||||
|
@ -138,14 +138,11 @@ namespace MCGalaxy {
|
||||
SendMessage("&cPlease complete admin verification with %T/Pass [Password]!");
|
||||
}
|
||||
|
||||
try {
|
||||
if (group.CanExecute("Inbox") && Database.TableExists("Inbox" + name) ) {
|
||||
using (DataTable table = Database.Backend.GetRows("Inbox" + name, "*")) {
|
||||
if (table.Rows.Count > 0)
|
||||
SendMessage("You have &a" + table.Rows.Count + " %Smessages in %T/Inbox");
|
||||
}
|
||||
if (group.CanExecute("Inbox") && Database.TableExists("Inbox" + name)) {
|
||||
int count = Database.CountRows("Inbox" + name);
|
||||
if (count > 0) {
|
||||
SendMessage("You have &a" + count + " %Smessages in %T/Inbox");
|
||||
}
|
||||
} catch {
|
||||
}
|
||||
|
||||
if (ServerConfig.PositionUpdateInterval > 1000)
|
||||
@ -216,16 +213,17 @@ namespace MCGalaxy {
|
||||
}
|
||||
|
||||
void GetPlayerStats() {
|
||||
DataTable data = Database.Backend.GetRows("Players", "*", "WHERE Name=@0", name);
|
||||
if (data.Rows.Count == 0) {
|
||||
object raw = Database.Backend.IterateRows("Players", "*",
|
||||
null, PlayerData.IteratePlayerData,
|
||||
"WHERE Name=@0", name);
|
||||
if (raw == null) {
|
||||
PlayerData.Create(this);
|
||||
Chat.MessageFrom(this, "λNICK %Shas connected for the first time!");
|
||||
SendMessage("Welcome " + ColoredName + "%S! This is your first visit.");
|
||||
} else {
|
||||
PlayerData.Load(data, this);
|
||||
PlayerData.Apply((PlayerData)raw, this);
|
||||
SendMessage("Welcome back " + FullName + "%S! You've been here " + TimesVisited + " times!");
|
||||
}
|
||||
data.Dispose();
|
||||
gotSQLData = true;
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ 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;
|
||||
@ -26,7 +26,7 @@ namespace MCGalaxy {
|
||||
/// <remarks> Note this field is highly volatile, you should cache references to the items array. </remarks>
|
||||
public static VolatileArray<Player> Online = new VolatileArray<Player>(true);
|
||||
|
||||
public static Group GetGroup(string name) {
|
||||
public static Group GetGroup(string name) {
|
||||
Player target = FindExact(name);
|
||||
return target != null ? target.group : Group.GroupIn(name);
|
||||
}
|
||||
@ -34,10 +34,10 @@ namespace MCGalaxy {
|
||||
public static string GetColoredName(Player p, string name) {
|
||||
Player target = FindExact(name);
|
||||
// TODO: select color from database?
|
||||
return target != null && Entities.CanSee(p, target) ? target.ColoredName
|
||||
return target != null && Entities.CanSee(p, target) ? target.ColoredName
|
||||
: Group.GroupIn(name).Color + name.RemoveLastPlus();
|
||||
}
|
||||
|
||||
|
||||
public static int NonHiddenCount() {
|
||||
Player[] players = Online.Items;
|
||||
int count = 0;
|
||||
@ -49,7 +49,7 @@ namespace MCGalaxy {
|
||||
int matches = 0; return FindMatches(pl, name, out matches, onlyCanSee);
|
||||
}
|
||||
|
||||
public static Player FindMatches(Player pl, string name,
|
||||
public static Player FindMatches(Player pl, string name,
|
||||
out int matches, bool onlyCanSee = true) {
|
||||
matches = 0;
|
||||
if (!Formatter.ValidName(pl, name, "player")) return null;
|
||||
@ -65,7 +65,7 @@ namespace MCGalaxy {
|
||||
Player target = FindMatches(p, name, out matches);
|
||||
|
||||
if (matches > 1) return null;
|
||||
if (target != null) return target.name;
|
||||
if (target != null) return target.name;
|
||||
Player.Message(p, "Searching PlayerDB for \"{0}\"..", name);
|
||||
return FindOfflineNameMatches(p, name);
|
||||
}
|
||||
@ -80,36 +80,24 @@ namespace MCGalaxy {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Retrieves from the database the player data for the player
|
||||
/// whose name caselessly exactly matches the given name. </summary>
|
||||
/// <returns> PlayerData instance if found, null if not. </returns>
|
||||
|
||||
public static PlayerData FindData(string name) {
|
||||
using (DataTable results = Query(name, "*")) {
|
||||
if (results.Rows.Count == 0) return null;
|
||||
return PlayerData.Fill(results.Rows[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Retrieves from the database the actual name for the player
|
||||
/// whose name caselessly exactly matches the given name. </summary>
|
||||
/// <returns> Correctly cased name if found, null if not. </returns>
|
||||
public static string FindName(string name) {
|
||||
using (DataTable playerDB = Query(name, "Name")) {
|
||||
if (playerDB.Rows.Count == 0) return null;
|
||||
return playerDB.Rows[0]["Name"].ToString().Trim();
|
||||
}
|
||||
string suffix = Database.Backend.CaselessWhereSuffix;
|
||||
object raw = Database.Backend.IterateRows("Players", "*",
|
||||
null, PlayerData.IteratePlayerData,
|
||||
"WHERE Name=@0" + suffix, name);
|
||||
return (PlayerData)raw;
|
||||
}
|
||||
|
||||
/// <summary> Retrieves from the database the last IP address for the
|
||||
/// player whose name caselessly exactly matches the given name. </summary>
|
||||
/// <returns> Last IP address if found, null if not. </returns>
|
||||
public static string FindName(string name) {
|
||||
string suffix = Database.Backend.CaselessWhereSuffix;
|
||||
return Database.GetString("Players", "Name", "WHERE Name=@0" + suffix, name);
|
||||
}
|
||||
|
||||
public static string FindIP(string name) {
|
||||
using (DataTable results = Query(name, "IP")) {
|
||||
if (results.Rows.Count == 0) return null;
|
||||
return results.Rows[0]["IP"].ToString().Trim();
|
||||
}
|
||||
string suffix = Database.Backend.CaselessWhereSuffix;
|
||||
return Database.GetString("Players", "IP", "WHERE Name=@0" + suffix, name);
|
||||
}
|
||||
|
||||
|
||||
@ -135,39 +123,33 @@ namespace MCGalaxy {
|
||||
return row == null ? null : row["Name"].ToString();
|
||||
}
|
||||
|
||||
static object IterateAccounts(IDataRecord record, object arg) {
|
||||
List<string> names = (List<string>)arg;
|
||||
string name = record.GetString(0);
|
||||
|
||||
if (!names.CaselessContains(name)) names.Add(name);
|
||||
return arg;
|
||||
}
|
||||
|
||||
/// <summary> Retrieves names of all players whose IP address matches the given IP address. </summary>
|
||||
/// <remarks> This is current IP for online players, last IP for offline players from the database. </remarks>
|
||||
public static List<string> FindAccounts(string ip) {
|
||||
DataTable clones = Database.Backend.GetRows("Players", "Name", "WHERE IP=@0", ip);
|
||||
List<string> accounts = new List<string>();
|
||||
|
||||
foreach (DataRow row in clones.Rows) {
|
||||
string name = row["Name"].ToString();
|
||||
if (!accounts.CaselessContains(name))
|
||||
accounts.Add(name);
|
||||
}
|
||||
List<string> names = new List<string>();
|
||||
Database.Backend.IterateRows("Players", "Name", names, IterateAccounts,
|
||||
"WHERE IP=@0", ip);
|
||||
|
||||
// TODO: should we instead do save() when the player logs in
|
||||
// by checking online players we avoid a DB write though
|
||||
Player[] players = PlayerInfo.Online.Items;
|
||||
foreach (Player p in players) {
|
||||
if (p.ip != ip) continue;
|
||||
if (!accounts.CaselessContains(p.name))
|
||||
accounts.Add(p.name);
|
||||
if (!names.CaselessContains(p.name)) names.Add(p.name);
|
||||
}
|
||||
|
||||
clones.Dispose();
|
||||
return accounts;
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal static DataTable Query(string name, string columns) {
|
||||
string suffix = Database.Backend.CaselessWhereSuffix;
|
||||
return Database.Backend.GetRows("Players", columns,
|
||||
"WHERE Name=@0" + suffix, name);
|
||||
}
|
||||
|
||||
internal static DataRow QueryMulti(Player p, string name, string columns) {
|
||||
static DataRow QueryMulti(Player p, string name, string columns) {
|
||||
string suffix = Database.Backend.CaselessLikeSuffix;
|
||||
using (DataTable results = Database.Backend.GetRows("Players", columns,
|
||||
"WHERE Name LIKE @0 ESCAPE '#' LIMIT 21" + suffix,
|
||||
|
@ -212,10 +212,8 @@ namespace MCGalaxy.Tasks {
|
||||
|
||||
|
||||
internal static void UpgradeDBTimeSpent(SchedulerTask task) {
|
||||
DataTable table = Database.Backend.GetRows(PlayerData.DBTable, "TimeSpent", "LIMIT 1");
|
||||
if (table.Rows.Count == 0) return; // no players
|
||||
|
||||
string time = table.Rows[0]["TimeSpent"].ToString();
|
||||
string time = Database.GetString("Players", "TimeSpent", "LIMIT 1");
|
||||
if (time == null) return; // no players at all in DB
|
||||
if (time.IndexOf(' ') == -1) return; // already upgraded
|
||||
|
||||
Logger.Log(LogType.SystemActivity, "Upgrading TimeSpent column in database to new format..");
|
||||
@ -232,10 +230,10 @@ namespace MCGalaxy.Tasks {
|
||||
static void DumpPlayerTimeSpents() {
|
||||
playerIds = new List<int>();
|
||||
playerSeconds = new List<long>();
|
||||
Database.Iterate("SELECT ID, TimeSpent FROM Players", AddPlayerTimeSpent);
|
||||
Database.Backend.IterateRows("Players", "ID,TimeSpent", null, IterateTimeSpent);
|
||||
}
|
||||
|
||||
static bool AddPlayerTimeSpent(IDataRecord record) {
|
||||
static object IterateTimeSpent(IDataRecord record, object arg) {
|
||||
playerCount++;
|
||||
try {
|
||||
int id = record.GetInt32(0);
|
||||
@ -246,10 +244,10 @@ namespace MCGalaxy.Tasks {
|
||||
} catch {
|
||||
playerFailed++;
|
||||
}
|
||||
return true;
|
||||
return arg;
|
||||
}
|
||||
|
||||
static void UpgradePlayerTimeSpents() {
|
||||
static void UpgradePlayerTimeSpents() {
|
||||
using (BulkTransaction bulk = Database.Backend.CreateBulk()) {
|
||||
IDataParameter idParam = bulk.CreateParam("@0", DbType.Int32);
|
||||
IDataParameter secsParam = bulk.CreateParam("@1", DbType.Int64);
|
||||
|
Loading…
x
Reference in New Issue
Block a user