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