diff --git a/CLI/Program.cs b/CLI/Program.cs index 58b4db1d6..77af7b603 100644 --- a/CLI/Program.cs +++ b/CLI/Program.cs @@ -217,7 +217,8 @@ public static class Program { if (part.Length == 0) continue; ConsoleColor color = GetConsoleColor(curCol); - if (color == ConsoleColor.White) { + if (color == ConsoleColor.White) { + // show in user's preferred console text color Console.ResetColor(); } else { Console.ForegroundColor = color; diff --git a/MCGalaxy/Database/Backends/MySQL.cs b/MCGalaxy/Database/Backends/MySQL.cs index 49d322577..1d40d9236 100644 --- a/MCGalaxy/Database/Backends/MySQL.cs +++ b/MCGalaxy/Database/Backends/MySQL.cs @@ -22,9 +22,10 @@ using System.Text; using MySql.Data.MySqlClient; -namespace MCGalaxy.SQL { - - public sealed class MySQLBackend : IDatabaseBackend { +namespace MCGalaxy.SQL +{ + public sealed class MySQLBackend : IDatabaseBackend + { public static IDatabaseBackend Instance = new MySQLBackend(); public MySQLBackend() { // MySQL uses case insensitive collation by default @@ -33,7 +34,8 @@ public sealed class MySQLBackend : IDatabaseBackend { } public override bool EnforcesTextLength { get { return true; } } - public override bool MultipleSchema { get { return true; } } + public override bool MultipleSchema { get { return true; } } + public override string EngineName { get { return "MySQL"; } } internal override IDbConnection CreateConnection() { const string format = "Data Source={0};Port={1};User ID={2};Password={3};Pooling={4};Treat Tiny As Boolean=false;"; @@ -51,6 +53,9 @@ public sealed class MySQLBackend : IDatabaseBackend { } + public override void LoadDependencies() { + } + public override void CreateDatabase() { string sql = "CREATE DATABASE if not exists `" + Server.Config.MySQLDatabaseName + "`"; Database.Do(sql, true, null, null); diff --git a/MCGalaxy/Database/Backends/SQLite.cs b/MCGalaxy/Database/Backends/SQLite.cs index d1a4421f1..2fddce14a 100644 --- a/MCGalaxy/Database/Backends/SQLite.cs +++ b/MCGalaxy/Database/Backends/SQLite.cs @@ -21,17 +21,19 @@ using System.IO; using System.Text; -namespace MCGalaxy.SQL { - - public sealed class SQLiteBackend : IDatabaseBackend { +namespace MCGalaxy.SQL +{ + public sealed class SQLiteBackend : IDatabaseBackend + { public static IDatabaseBackend Instance = new SQLiteBackend(); public SQLiteBackend() { CaselessWhereSuffix = " COLLATE NOCASE"; - CaselessLikeSuffix = " COLLATE NOCASE"; + CaselessLikeSuffix = " COLLATE NOCASE"; } public override bool EnforcesTextLength { get { return false; } } public override bool MultipleSchema { get { return false; } } + public override string EngineName { get { return "SQLite"; } } internal override IDbConnection CreateConnection() { return new MCGSQLiteConnection(); @@ -43,9 +45,26 @@ public sealed class SQLiteBackend : IDatabaseBackend { internal override IDbDataParameter CreateParameter() { return new SQLiteParameter(); + } + + + public override void LoadDependencies() { + // on macOS/Linux, use the system provided sqlite3 native library + if (!IOperatingSystem.DetectOS().IsWindows) return; + + Server.CheckFile("sqlite3_x32.dll"); + Server.CheckFile("sqlite3_x64.dll"); + + // sqlite3.dll is the .DLL that MCGalaxy will actually load on Windows + try { + string dll = IntPtr.Size == 8 ? "sqlite3_x64.dll" : "sqlite3_x32.dll"; + if (File.Exists(dll)) File.Copy(dll, "sqlite3.dll", true); + } catch (Exception ex) { + // e.g. can happen when multiple server instances running + Logger.LogError("Error moving SQLite dll", ex); + } } - - + public override void CreateDatabase() { } public override string RawGetDateTime(IDataRecord record, int col) { diff --git a/MCGalaxy/Database/IDatabaseBackend.cs b/MCGalaxy/Database/IDatabaseBackend.cs index a2feaf7e0..0b479be52 100644 --- a/MCGalaxy/Database/IDatabaseBackend.cs +++ b/MCGalaxy/Database/IDatabaseBackend.cs @@ -30,6 +30,7 @@ public abstract class IDatabaseBackend public abstract bool EnforcesTextLength { get; } /// Whether this backend supports multiple database schemas. public abstract bool MultipleSchema { get; } + public abstract string EngineName { get; } internal abstract IDbConnection CreateConnection(); internal abstract IDbCommand CreateCommand(string sql, IDbConnection conn); @@ -41,6 +42,8 @@ public abstract class IDatabaseBackend public string CaselessLikeSuffix { get; protected set; } + /// Downloads and/or moves required DLLs + public abstract void LoadDependencies(); /// Creates the schema for this database (if required). public abstract void CreateDatabase(); diff --git a/MCGalaxy/Database/PlayerData.cs b/MCGalaxy/Database/PlayerData.cs index 9a24d5d40..bbb5169e8 100644 --- a/MCGalaxy/Database/PlayerData.cs +++ b/MCGalaxy/Database/PlayerData.cs @@ -62,12 +62,12 @@ public class PlayerData { "totalDeaths, Money, totalBlocks, totalKicked, Messages, TimeSpent", p.name, p.ip, now, now, 1, "", 0, 0, 0, 0, 0, (long)p.TotalTime.TotalSeconds); - int id = -100000; + int id = -200; Database.ReadRows("Players", "ID", record => id = record.GetInt32(0), "WHERE Name=@0", p.name); - if (id >= 0) { + if (id != -200) { p.DatabaseID = id; } else { p.DatabaseID = NameConverter.InvalidNameID(p.name); @@ -136,7 +136,6 @@ record => id = record.GetInt32(0), data.TotalDeleted = UnpackHi(drawn); return data; } - internal static object Read(IDataRecord record, object arg) { return Parse(record); } internal static long ParseLong(string value) { return (value.Length == 0 || value.CaselessEq("null")) ? 0 : long.Parse(value); diff --git a/MCGalaxy/Server/OperatingSystem.cs b/MCGalaxy/Server/OperatingSystem.cs index 300cf29a3..b18647d6a 100644 --- a/MCGalaxy/Server/OperatingSystem.cs +++ b/MCGalaxy/Server/OperatingSystem.cs @@ -35,9 +35,16 @@ public abstract class IOperatingSystem /// Does not return when restart is successful /// (since current process image is replaced) public abstract void RestartProcess(); + public abstract bool IsWindows { get; } + static IOperatingSystem detectedOS; public unsafe static IOperatingSystem DetectOS() { + detectedOS = detectedOS ?? DoDetectOS(); + return detectedOS; + } + + unsafe static IOperatingSystem DoDetectOS() { PlatformID platform = Environment.OSVersion.Platform; if (platform == PlatformID.Win32NT || platform == PlatformID.Win32Windows) return new WindowsOS(); @@ -71,6 +78,7 @@ class WindowsOS : IOperatingSystem static extern int GetSystemTimes(out ulong idleTime, out ulong kernelTime, out ulong userTime); public override void RestartProcess() { } + public override bool IsWindows { get { return true; } } } class macOS : UnixOS @@ -134,6 +142,7 @@ class UnixOS : IOperatingSystem public override void RestartProcess() { if (Server.CLIMode) HACK_Execvp(); } + public override bool IsWindows { get { return false; } } #if !NETSTANDARD [DllImport("libc", SetLastError = true)] diff --git a/MCGalaxy/Server/Server.DB.cs b/MCGalaxy/Server/Server.DB.cs index 3b65d63df..542798ccd 100644 --- a/MCGalaxy/Server/Server.DB.cs +++ b/MCGalaxy/Server/Server.DB.cs @@ -53,7 +53,8 @@ public sealed partial class Server { static void InitDatabase() { if (!Directory.Exists("blockdb")) Directory.CreateDirectory("blockdb"); - + + Logger.Log(LogType.SystemActivity, "Using {0} for database backend", Database.Backend.EngineName); try { Database.Backend.CreateDatabase(); } catch (Exception e) { diff --git a/MCGalaxy/Server/Server.cs b/MCGalaxy/Server/Server.cs index a21c566ff..9024071de 100644 --- a/MCGalaxy/Server/Server.cs +++ b/MCGalaxy/Server/Server.cs @@ -20,7 +20,6 @@ using System.Diagnostics; using System.IO; using System.Net; -using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; using System.Threading; @@ -33,6 +32,7 @@ using MCGalaxy.Games; using MCGalaxy.Network; using MCGalaxy.Scripting; +using MCGalaxy.SQL; using MCGalaxy.Tasks; using MCGalaxy.Util; using MCGalaxy.Modules.Awards; @@ -60,7 +60,7 @@ public sealed partial class Server Logger.Log(type, message); } - static void CheckFile(string file) { + public static void CheckFile(string file) { if (File.Exists(file)) return; Logger.Log(LogType.SystemActivity, file + " doesn't exist, Downloading.."); @@ -91,14 +91,12 @@ public sealed partial class Server shuttingDown = false; Logger.Log(LogType.SystemActivity, "Starting Server"); ServicePointManager.Expect100Continue = false; - ForceEnableTLS(); - - CheckFile("MySql.Data.dll"); - CheckFile("sqlite3_x32.dll"); - CheckFile("sqlite3_x64.dll"); + ForceEnableTLS(); + + SQLiteBackend.Instance.LoadDependencies(); + CheckFile("MySql.Data.dll"); // TODO move to MySQL backend ? EnsureFilesExist(); - MoveSqliteDll(); MoveOutdatedFiles(); LoadAllSettings(); @@ -128,15 +126,6 @@ public sealed partial class Server try { ServicePointManager.SecurityProtocol |= (SecurityProtocolType)0xC00; } catch { } } - static void MoveSqliteDll() { - try { - string dll = IntPtr.Size == 8 ? "sqlite3_x64.dll" : "sqlite3_x32.dll"; - if (File.Exists(dll)) File.Copy(dll, "sqlite3.dll", true); - } catch (Exception ex) { - Logger.LogError("Error moving SQLite dll", ex); - } - } - static void EnsureFilesExist() { EnsureDirectoryExists("properties"); EnsureDirectoryExists("levels");