/// <summary> /// Prepares logging. /// </summary> /// <param name="configuration">Configuration to use.</param> public static void SetConfiguration(UchuConfiguration configuration) { // Get the log levels. They are used referenced twice. var consoleLogLevel = LogLevel.Debug; var fileLogLevel = LogLevel.None; if (Enum.TryParse <LogLevel>(configuration?.ConsoleLogging.Level, out var newConsoleLogLevel)) { consoleLogLevel = newConsoleLogLevel; } if (Enum.TryParse <LogLevel>(configuration?.FileLogging.Level, out var newFileLogLevel)) { fileLogLevel = newFileLogLevel; } // Add console logging. if (consoleLogLevel != LogLevel.None) { NexusLogger.Outputs.Add(new ConsoleOutput() { IncludeDate = configuration?.ConsoleLogging.Timestamp ?? false, NamespaceWhitelist = new List <string>() { "Uchu" }, MinimumLevel = consoleLogLevel, }); } // Add file logging. if (fileLogLevel != LogLevel.None) { NexusLogger.Outputs.Add(new FileOutput() { IncludeDate = configuration?.FileLogging.Timestamp ?? false, NamespaceWhitelist = new List <string>() { "Uchu" }, MinimumLevel = fileLogLevel, FileLocation = configuration?.FileLogging.File ?? "uchu.log", }); } }
private async Task ConfigureAsync(string config) { var serializer = new XmlSerializer(typeof(UchuConfiguration)); if (!File.Exists(config)) { throw new ArgumentException($"{config} config file does not exist."); } var uchuConfiguration = UchuConfiguration.Load(config); UchuContextBase.Config = uchuConfiguration; var masterPath = Path.GetDirectoryName(config); SqliteContext.DatabasePath = Path.Combine(masterPath, "./Uchu.sqlite"); var api = new ApiManager(uchuConfiguration.ApiConfig.Protocol, uchuConfiguration.ApiConfig.Domain); var instance = await api.RunCommandAsync <InstanceInfoResponse>( uchuConfiguration.ApiConfig.Port, $"instance/target?i={Id}" ).ConfigureAwait(false); if (!instance.Success) { Logger.Error(instance.FailedReason); throw new Exception(instance.FailedReason); } UchuServer = instance.Info.Type == (int)ServerType.World ? new WorldUchuServer(Id) : new UchuServer(Id); Console.Title = $"{(ServerType) instance.Info.Type}:{instance.Info.Port}"; ServerType = (ServerType)instance.Info.Type; await UchuServer.ConfigureAsync(config); }
private static async Task ConfigureAsync() { var serializer = new XmlSerializer(typeof(UchuConfiguration)); var fn = File.Exists("config.xml") ? "config.xml" : "config.default.xml"; if (File.Exists(fn)) { await using var file = File.OpenRead(fn); Logger.Config = Config = (UchuConfiguration)serializer.Deserialize(file); } else { Logger.Config = Config = new UchuConfiguration(); var backup = File.CreateText("config.default.xml"); serializer.Serialize(backup, Config); backup.Close(); Logger.Warning("No config file found, creating default."); var info = new FileInfo("config.default.xml"); Logger.Information($"You may now continue with configuring Uchu. Default config file located at: {info.FullName}"); throw new FileNotFoundException("No config file found.", info.FullName); } SqliteContext.DatabasePath = Path.Combine(Directory.GetCurrentDirectory(), "./Uchu.sqlite"); UchuContextBase.Config = Config; var configPath = Config.ResourcesConfiguration?.GameResourceFolder; if (!string.IsNullOrWhiteSpace(configPath)) { if (EnsureUnpackedClient(configPath)) { Logger.Information($"Using local resources at `{Config.ResourcesConfiguration.GameResourceFolder}`"); } else { Logger.Error($"Invalid local resources (Invalid path or no .luz files found). Please ensure you are using an unpacked client."); throw new FileNotFoundException("No luz files found."); } } else { Logger.Error("No input location of local resources. Please input in config file."); throw new DirectoryNotFoundException("No local resource path."); } UseAuthentication = Config.Networking.HostAuthentication; DllLocation = Config.DllSource.Instance; ApiPortIndex = Config.ApiConfig.Port; var source = Directory.GetCurrentDirectory(); ConfigPath = Path.Combine(source, $"{fn}"); CdClientPath = Path.Combine(source, "CDClient.db"); Logger.Information($"{source}\n{ConfigPath}\n{CdClientPath}"); }
public LocalResources(UchuConfiguration config) { _config = config; }
/// <summary> /// Load the server configuration. /// </summary> /// <exception cref="DirectoryNotFoundException">Resource folder is not configured correctly.</exception> /// <exception cref="FileNotFoundException">One of the required files are not configured correctly.</exception> private static async Task ConfigureAsync() { const string configFilename = "config.xml"; const string legacySecondConfigName = "config.default.xml"; // Use config.xml if it exists if (File.Exists(configFilename)) { Config = UchuConfiguration.Load(configFilename); Logger.SetConfiguration(Config); #if DEBUG if (!Config.DebugConfig.StartInstancesAsThreads) #endif Logger.SetServerTypeInformation("Master"); } // Otherwise, use config.default.xml if it exists else if (File.Exists(legacySecondConfigName)) { Config = UchuConfiguration.Load(legacySecondConfigName); Logger.SetConfiguration(Config); #if DEBUG if (!Config.DebugConfig.StartInstancesAsThreads) #endif Logger.SetServerTypeInformation("Master"); } // Otherwise, generate a new config file else { Config = new UchuConfiguration(); Logger.SetConfiguration(Config); #if DEBUG if (!Config.DebugConfig.StartInstancesAsThreads) #endif Logger.SetServerTypeInformation("Master"); // Add default value for instance DLL source and script DLL source. if (File.Exists("lib/Uchu.Instance.dll")) { Config.DllSource.Instance = "lib/Uchu.Instance.dll"; } Config.DllSource.ScriptDllSource.Add(File.Exists("lib/Uchu.StandardScripts.dll") ? "lib/Uchu.StandardScripts.dll" : "../../../../Uchu.StandardScripts/bin/Debug/net6.0/Uchu.StandardScripts.dll"); // Write config file Config.Save(configFilename); var info = new FileInfo(configFilename); Logger.Warning($"No config file found, created one at {info.FullName}"); } SqliteContext.DatabasePath = Path.Combine(Directory.GetCurrentDirectory(), "./Uchu.sqlite"); UchuContextBase.Config = Config; UseAuthentication = Config.Networking.HostAuthentication; // Check: resource folder var resourceFolder = Config.ResourcesConfiguration.GameResourceFolder; if (!EnsureUnpackedClient(resourceFolder)) { // Try finding NLUL client try { Config.ResourcesConfiguration.GameResourceFolder = FindNlulClientResources(); Config.Save(configFilename); Logger.Information($"Using automatically detected client resource folder: {Config.ResourcesConfiguration.GameResourceFolder}"); } catch { // Unsuccessful in finding unpacked client resource folder throw new DirectoryNotFoundException( "Please enter a valid unpacked client resource folder in the configuration file."); } } // Check: Uchu.Instance.dll // Migration from .net 5 to .net 6 if (Config.DllSource.Instance.Contains("net5.0")) { Config.DllSource.Instance = Config.DllSource.Instance.Replace("net5.0", "net6.0"); Config.Save(configFilename); } DllLocation = Config.DllSource.Instance; if (!File.Exists(DllLocation)) { throw new FileNotFoundException("Could not find file specified in <Instance> under <DllSource> in config.xml."); } // Check: Uchu.StandardScripts.dll var validScriptPackExists = false; for (var i = 0; i < Config.DllSource.ScriptDllSource.Count; i++) { // Migration from .net 5 to .net 6 if (Config.DllSource.ScriptDllSource[i].Contains("net5.0")) { Config.DllSource.ScriptDllSource[i] = Config.DllSource.ScriptDllSource[i].Replace("net5.0", "net6.0"); Config.Save(configFilename); } if (File.Exists(Config.DllSource.ScriptDllSource[i])) { Logger.Information($"Using script pack: {Config.DllSource.ScriptDllSource[i]}"); validScriptPackExists = true; break; } Logger.Warning($"Could not find script pack at {Config.DllSource.ScriptDllSource[i]}"); } if (!validScriptPackExists) { throw new FileNotFoundException("No valid <ScriptDllSource> specified under <DllSource> in config.xml.\n" + "Without Uchu.StandardScripts.dll, Uchu cannot function correctly."); } ApiPortIndex = Config.ApiConfig.Port; WorldServerHeartBeatsPerInterval = Config.Networking.WorldServerHeartBeatsPerInterval; WorldServerHeartBeatsIntervalInMinutes = Config.Networking.WorldServerHeartBeatIntervalInMinutes; var source = Directory.GetCurrentDirectory(); ConfigPath = Path.Combine(source, $"{configFilename}"); CdClientPath = Path.Combine(source, "CDClient.db"); Logger.Information($"Using configuration: {ConfigPath}\nUsing CDClient: {CdClientPath}"); }
/// <summary> /// Configures the server by parsing config files and setting up certificates. /// </summary> /// <param name="configFile">The config file to use as configuration</param> /// <exception cref="ArgumentException">If the provided config file can't be found</exception> public virtual async Task ConfigureAsync(string configFile) { if (configFile == null) { throw new ArgumentNullException(nameof(configFile), ResourceStrings.Server_ConfigureAsync_ConfigFileNullException); } MasterPath = Path.GetDirectoryName(configFile); Config = UchuConfiguration.Load(configFile); if (!Config.DebugConfig.StartInstancesAsThreads) { Logger.SetConfiguration(Config); } UchuContextBase.Config = Config; if (!File.Exists(configFile)) { throw new ArgumentException($"{configFile} config file does not exist."); } await SetupApiAsync().ConfigureAwait(false); if (!string.IsNullOrWhiteSpace(Config.ResourcesConfiguration?.GameResourceFolder)) { Resources = new LocalResources(Config); } // Setup the RakNet server and possible certificate var certificateFilePath = Path.Combine(MasterPath, Config.Networking.Certificate); if (Config.Networking?.Certificate != default && File.Exists(certificateFilePath)) { var cert = new X509Certificate2(certificateFilePath); Logger.Information($"PRIVATE KEY: {cert.HasPrivateKey} {cert.PrivateKey}"); Certificate = cert; RakNetServer = new TcpUdpServer(Port, "3.25 ND1", Certificate, 150); } else { RakNetServer = new TcpUdpServer(Port, "3.25 ND1"); } SsoService = new SsoService(Config.SsoConfig?.Domain ?? ""); // Try to connect to Redis, otherwise fallback to DB caching if (Config.CacheConfig.UseService) { try { SessionCache = new RedisSessionCache(Config.CacheConfig); Logger.Information($"Established Redis connection at {Config.CacheConfig.Host}:{Config.CacheConfig.Port}"); } catch (RedisConnectionException) { Logger.Error("Failed to establish Redis connection, falling back to database."); SessionCache = new DatabaseCache(); } } else { Logger.Information("Caching service is disabled, falling back to database."); SessionCache = new DatabaseCache(); } HeartBeatsPerInterval = Config.Networking.WorldServerHeartBeatsPerInterval; HeartBeatIntervalInMinutes = Config.Networking.WorldServerHeartBeatIntervalInMinutes; Logger.Information($"Server {Id} configured on port: {Port}"); }