/// <summary> /// Creates a new Server instance. /// </summary> /// <param name="version">Version the server is running. <i>(independent of minecraft version)</i></param> public Server(Config config, string version, int serverId) { this.Config = config; ServerImplementationRegistry.RegisterServerImplementations(); this.LoggerProvider = new LoggerProvider(LogLevel.Debug); this.Logger = this.LoggerProvider.CreateLogger($"Server/{this.Id}"); // This stuff down here needs to be looked into Globals.PacketLogger = this.LoggerProvider.CreateLogger("Packets"); PacketDebug.Logger = this.LoggerProvider.CreateLogger("PacketDebug"); Registry.Logger = this.LoggerProvider.CreateLogger("Registry"); this.Port = config.Port; this.Version = version; this.Id = serverId; this.tcpListener = new TcpListener(IPAddress.Any, this.Port); this.clients = new ConcurrentHashSet <Client>(); this.cts = new CancellationTokenSource(); this.chatMessages = new ConcurrentQueue <QueueChat>(); this.placed = new ConcurrentQueue <PlayerBlockPlacement>(); Logger.LogDebug("Initializing command handler..."); this.Commands = new CommandHandler("/"); Logger.LogDebug("Registering commands..."); this.Commands.RegisterCommandClass <MainCommandModule>(); Logger.LogDebug("Registering custom argument parsers..."); this.Commands.AddArgumentParser(new LocationTypeParser()); this.Commands.AddArgumentParser(new PlayerTypeParser()); Logger.LogDebug("Registering command context type..."); this.Commands.RegisterContextType <ObsidianContext>(); Logger.LogDebug("Done registering commands."); this.Events = new MinecraftEventHandler(); this.PluginManager = new PluginManager(Events, this, LoggerProvider.CreateLogger("Plugin Manager")); this.Operators = new OperatorList(this); this.World = new World("world", this); this.Events.PlayerLeave += this.OnPlayerLeave; this.Events.PlayerJoin += this.OnPlayerJoin; this.Events.ServerTick += this.OnServerTick; }
/// <summary> /// Starts this server asynchronously. /// </summary> public async Task StartServerAsync() { this.StartTime = DateTimeOffset.Now; this.Logger.LogInformation($"Launching Obsidian Server v{Version} with ID {Id}"); var stopwatch = Stopwatch.StartNew(); // Check if MPDM and OM are enabled, if so, we can't handle connections if (this.Config.MulitplayerDebugMode && this.Config.OnlineMode) { this.Logger.LogError("Incompatible Config: Multiplayer debug mode can't be enabled at the same time as online mode since usernames will be overwritten"); this.StopServer(); return; } await Task.WhenAll(Registry.RegisterBlocksAsync(), Registry.RegisterItemsAsync(), Registry.RegisterBiomesAsync(), Registry.RegisterDimensionsAsync(), Registry.RegisterTagsAsync(), Registry.RegisterRecipesAsync()); Block.Initialize(); Cube.Initialize(); ServerImplementationRegistry.RegisterServerImplementations(); this.Logger.LogInformation($"Loading properties..."); await(this.Operators as OperatorList).InitializeAsync(); await this.RegisterDefaultAsync(); this.ScoreboardManager = new ScoreboardManager(this); this.Logger.LogInformation("Loading plugins..."); Directory.CreateDirectory(Path.Join(ServerFolderPath, "plugins")); // Creates if doesn't exist. this.PluginManager.DirectoryWatcher.Filters = new[] { ".cs", ".dll" }; this.PluginManager.DefaultPermissions = API.Plugins.PluginPermissions.All; this.PluginManager.DirectoryWatcher.Watch(Path.Join(ServerFolderPath, "plugins")); await Task.WhenAll(Config.DownloadPlugins.Select(path => PluginManager.LoadPluginAsync(path))); this.World = new World("world1", this); if (!this.World.Load()) { if (!this.WorldGenerators.TryGetValue(this.Config.Generator, out WorldGenerator value)) { this.Logger.LogWarning($"Unknown generator type {this.Config.Generator}"); } var gen = value ?? new SuperflatGenerator(); this.Logger.LogInformation($"Creating new {gen.Id} ({gen}) world..."); this.World.Init(gen); this.World.Save(); } if (!this.Config.OnlineMode) { this.Logger.LogInformation($"Starting in offline mode..."); } Registry.RegisterCommands(this); _ = Task.Run(this.ServerLoop); this.Logger.LogInformation($"Listening for new clients..."); stopwatch.Stop(); Logger.LogInformation($"Server-{Id} loaded in {stopwatch.Elapsed}"); this.tcpListener.Start(); while (!this.cts.IsCancellationRequested) { var tcp = await this.tcpListener.AcceptTcpClientAsync(); this.Logger.LogDebug($"New connection from client with IP {tcp.Client.RemoteEndPoint}"); var client = new Client(tcp, this.Config, Math.Max(0, this.clients.Count + this.World.TotalLoadedEntities()), this); this.clients.Add(client); client.Disconnected += client => clients.TryRemove(client); _ = Task.Run(client.StartConnectionAsync); } this.Logger.LogWarning("Server is shutting down..."); }