using System; using System.IO; using System.Linq; using Impostor.Api.Events.Managers; using Impostor.Api.Games; using Impostor.Api.Games.Managers; using Impostor.Api.Net.Manager; using Impostor.Api.Net.Messages; using Impostor.Hazel.Extensions; using Impostor.Server.Config; using Impostor.Server.Events; using Impostor.Server.Net; using Impostor.Server.Net.Factories; using Impostor.Server.Net.Manager; using Impostor.Server.Net.Messages; using Impostor.Server.Net.Redirector; using Impostor.Server.Plugins; using Impostor.Server.Recorder; using Impostor.Server.Utils; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.ObjectPool; using Serilog; using Serilog.Events; namespace Impostor.Server { internal static class Program { private static int Main(string[] args) { #if DEBUG var logLevel = LogEventLevel.Debug; #else var logLevel = LogEventLevel.Information; #endif if (args.Contains("--verbose")) { logLevel = LogEventLevel.Verbose; } else if (args.Contains("--errors-only")) { logLevel = LogEventLevel.Error; } Log.Logger = new LoggerConfiguration() .MinimumLevel.Is(logLevel) #if DEBUG .MinimumLevel.Override("Microsoft", LogEventLevel.Debug) #else .MinimumLevel.Override("Microsoft", LogEventLevel.Information) #endif .Enrich.FromLogContext() .WriteTo.Console() .CreateLogger(); try { Log.Information("Starting Impostor v{0}", DotnetUtils.GetVersion()); CreateHostBuilder(args).Build().Run(); return 0; } catch (Exception ex) { Log.Fatal(ex, "Impostor terminated unexpectedly"); return 1; } finally { Log.CloseAndFlush(); } } private static IConfiguration CreateConfiguration(string[] args) { var configurationBuilder = new ConfigurationBuilder(); configurationBuilder.AddJsonFile("config.json", true); configurationBuilder.AddJsonFile("config.Development.json", true); configurationBuilder.AddEnvironmentVariables(prefix: "IMPOSTOR_"); configurationBuilder.AddCommandLine(args); return configurationBuilder.Build(); } //c 入口 private static IHostBuilder CreateHostBuilder(string[] args) { var configuration = CreateConfiguration(args); var pluginConfig = configuration.GetSection("PluginLoader") .Get() ?? new PluginConfig(); return Host.CreateDefaultBuilder(args) .UseContentRoot(Directory.GetCurrentDirectory()) #if DEBUG .UseEnvironment(Environment.GetEnvironmentVariable("IMPOSTOR_ENV") ?? "Development") #else .UseEnvironment("Production") #endif .ConfigureAppConfiguration(builder => { builder.AddConfiguration(configuration); }) .ConfigureServices((host, services) => { var debug = host.Configuration .GetSection(DebugConfig.Section) .Get() ?? new DebugConfig(); var redirector = host.Configuration .GetSection(ServerRedirectorConfig.Section) .Get() ?? new ServerRedirectorConfig(); services.Configure(host.Configuration.GetSection(DebugConfig.Section)); services.Configure(host.Configuration.GetSection(AntiCheatConfig.Section)); services.Configure(host.Configuration.GetSection(ServerConfig.Section)); services.Configure(host.Configuration.GetSection(ServerRedirectorConfig.Section)); if (redirector.Enabled) { if (!string.IsNullOrEmpty(redirector.Locator.Redis)) { // When joining a game, it retrieves the game server ip from redis. // When a game has been created on this node, it stores the game code with its ip in redis. services.AddSingleton(); // Dependency for the NodeLocatorRedis. services.AddStackExchangeRedisCache(options => { options.Configuration = redirector.Locator.Redis; options.InstanceName = "ImpostorRedis"; }); } else if (!string.IsNullOrEmpty(redirector.Locator.UdpMasterEndpoint)) { services.AddSingleton(); if (redirector.Master) { services.AddHostedService(); } } else { throw new Exception("Missing a valid NodeLocator config."); } // Use the configuration as source for the list of nodes to provide // when creating a game. services.AddSingleton(); } else { // Redirector is not enabled but the dependency is still required. // So we provide one that ignores all calls. services.AddSingleton(); } services.AddSingleton(); services.AddSingleton(p => p.GetRequiredService()); if (redirector.Enabled && redirector.Master) { services.AddSingleton>(); // For a master server, we don't need a GameManager. } else { if (debug.GameRecorderEnabled) { services.AddSingleton(new DefaultObjectPoolProvider()); services.AddSingleton>(serviceProvider => { var provider = serviceProvider.GetRequiredService(); var policy = new PacketSerializationContextPooledObjectPolicy(); return provider.Create(policy); }); services.AddSingleton(); services.AddHostedService(sp => sp.GetRequiredService()); services.AddSingleton>(); } else { services.AddSingleton>(); } services.AddSingleton(); services.AddSingleton(p => p.GetRequiredService()); } services.AddHazel(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddHostedService(); }) .UseSerilog() .UseConsoleLifetime() .UsePluginLoader(pluginConfig); } } }