void ProcessCommand(string comName, string[] comArgs, bool exitAfterPrint)
        {
            string s = string.Empty;

            switch (comName.ToLower())
            {
            case "help":
                foreach (var com in new[] { "help", "quit", "clients", "blacklist [add/remove] [playerID/IP]", "whitelist [enable/disable/add/remove] [playerID/IP]", "songs [add/remove/start/list] [songID on BeatSaver]" })
                {
                    s += $"{Environment.NewLine}> {com}";
                }

                Logger.Instance.Log($"Commands:{s}", exitAfterPrint);
                break;

            case "version":
                Logger.Instance.Log($"{Assembly.GetEntryAssembly().GetName().Version}", exitAfterPrint);
                break;

            case "quit":
                Environment.Exit(0);
                return;

            case "clients":
                if (!exitAfterPrint)
                {
                    foreach (var t in clients)
                    {
                        var client = t.playerInfo;
                        if (t.playerInfo == null)
                        {
                            s +=
                                $"{Environment.NewLine}[{t.state}] NOT AVAILABLE @ {((IPEndPoint)t._client.Client.RemoteEndPoint).Address}";
                        }
                        else
                        {
                            s +=
                                $"{Environment.NewLine}[{t.state}] {client.playerName} @ {((IPEndPoint)t._client.Client.RemoteEndPoint).Address}";
                        }
                    }

                    if (s == String.Empty)
                    {
                        s = " No Clients";
                    }
                    Logger.Instance.Log($"Connected Clients:{s}", exitAfterPrint);
                }
                break;

            case "blacklist":
            {
                if (comArgs.Length == 2 && !comArgs[1].IsNullOrEmpty())
                {
                    switch (comArgs[0])
                    {
                    case "add":
                    {
                        if (!Settings.Instance.Access.Blacklist.Contains(comArgs[1]))
                        {
                            clients.Where(y => y.clientIP == comArgs[1] || y.playerId.ToString() == comArgs[1]).AsParallel().ForAll(z => z.KickClient());
                            Settings.Instance.Access.Blacklist.Add(comArgs[1]);
                            Logger.Instance.Log($"Successfully banned {comArgs[1]}", exitAfterPrint);
                            Settings.Instance.Save();
                        }
                        else
                        {
                            Logger.Instance.Log($"{comArgs[1]} is already blacklisted", exitAfterPrint);
                        }
                    }
                    break;

                    case "remove":
                    {
                        if (Settings.Instance.Access.Blacklist.Remove(comArgs[1]))
                        {
                            Logger.Instance.Log($"Successfully unbanned {comArgs[1]}", exitAfterPrint);
                            Settings.Instance.Save();
                        }
                        else
                        {
                            Logger.Instance.Warning($"{comArgs[1]} is not banned", exitAfterPrint);
                        }
                    }
                    break;

                    default:
                    {
                        Logger.Instance.Warning($"Command usage: blacklist [add/remove] [playerID/IP]", exitAfterPrint);
                    }
                    break;
                    }
                }
                else
                {
                    Logger.Instance.Warning($"Command usage: blacklist [add/remove] [playerID/IP]", exitAfterPrint);
                }
            }
            break;

            case "whitelist":
            {
                if (comArgs.Length >= 1)
                {
                    switch (comArgs[0])
                    {
                    case "enable":
                    {
                        Settings.Instance.Access.WhitelistEnabled = true;
                        Logger.Instance.Log($"Whitelist enabled", exitAfterPrint);
                        Settings.Instance.Save();
                    }
                    break;

                    case "disable":
                    {
                        Settings.Instance.Access.WhitelistEnabled = false;
                        Logger.Instance.Log($"Whitelist disabled", exitAfterPrint);
                        Settings.Instance.Save();
                    }
                    break;

                    case "add":
                    {
                        if (comArgs.Length == 2 && !comArgs[1].IsNullOrEmpty())
                        {
                            if (!Settings.Instance.Access.Whitelist.Contains(comArgs[1]))
                            {
                                Settings.Instance.Access.Whitelist.Add(comArgs[1]);
                                Settings.Instance.Save();
                                Logger.Instance.Log($"Successfully whitelisted {comArgs[1]}", exitAfterPrint);
                            }
                            else
                            {
                                Logger.Instance.Log($"{comArgs[1]} is already whitelisted", exitAfterPrint);
                            }
                        }
                        else
                        {
                            Logger.Instance.Warning($"Command usage: whitelist [enable/disable/add/remove] [playerID/IP]", exitAfterPrint);
                        }
                    }
                    break;

                    case "remove":
                    {
                        if (comArgs.Length == 2 && !comArgs[1].IsNullOrEmpty())
                        {
                            clients.Where(y => y.clientIP == comArgs[1] || y.playerId.ToString() == comArgs[1]).AsParallel().ForAll(z => z.KickClient());
                            if (Settings.Instance.Access.Whitelist.Remove(comArgs[1]))
                            {
                                Logger.Instance.Log($"Successfully removed {comArgs[1]} from whitelist", exitAfterPrint);
                                Settings.Instance.Save();
                            }
                            else
                            {
                                Logger.Instance.Warning($"{comArgs[1]} is not whitelisted", exitAfterPrint);
                            }
                        }
                        else
                        {
                            Logger.Instance.Warning($"Command usage: whitelist [enable/disable/add/remove] [playerID/IP]", exitAfterPrint);
                        }
                    }
                    break;

                    default:
                    {
                        Logger.Instance.Warning($"Command usage: whitelist [enable/disable/add/remove] [playerID/IP]", exitAfterPrint);
                    }
                    break;
                    }
                }
                else
                {
                    Logger.Instance.Warning($"Command usage: whitelist [enable/disable/add/remove] [playerID/IP]", exitAfterPrint);
                }
            }
            break;

            case "songs":
            {
                if (comArgs.Length >= 1)
                {
                    switch (comArgs[0])
                    {
                    case "add":
                    {
                        string songId = comArgs[1];
                        if (comArgs.Length == 2 && !comArgs[1].IsNullOrEmpty())
                        {
                            if (!Settings.Instance.AvailableSongs.Songs.Contains(songId))
                            {
                                List <string> songs = new List <string>(Settings.Instance.AvailableSongs.Songs);
                                songs.Add(songId);
                                Settings.Instance.AvailableSongs.Songs = songs.ToArray();
                                Settings.Instance.Save();
                                string path = DownloadSongByID(songId);

                                ProcessSong(SongLoader.GetCustomSongInfo(path));

                                Logger.Instance.Log($"Successfully added {comArgs[1]} to the song list", exitAfterPrint);

                                SendToAllClients(new ServerCommand(
                                                     ServerCommandType.DownloadSongs,
                                                     _songs: availableSongs.Select(y => y.levelId).ToArray()), wss);
                            }
                            else
                            {
                                Logger.Instance.Log($"{comArgs[1]} is already on the song list", exitAfterPrint);
                            }
                        }
                        else
                        {
                            Logger.Instance.Warning($"Command usage: songs [add/remove/start/list] [songID on BeatSaver]", exitAfterPrint);
                        }
                    }
                    break;

                    case "remove":
                    {
                        string songId = comArgs[1];
                        if (comArgs.Length == 2 && !comArgs[1].IsNullOrEmpty())
                        {
                            clients.Where(y => y.clientIP == comArgs[1] || y.playerId.ToString() == comArgs[1]).AsParallel().ForAll(z => z.KickClient());

                            List <string> songs = new List <string>(Settings.Instance.AvailableSongs.Songs);

                            if (songs.Remove(songId))
                            {
                                Settings.Instance.AvailableSongs.Songs = songs.ToArray();
                                Settings.Instance.Save();
                                availableSongs.RemoveAll(y => y.beatSaverId == songId);
                                Logger.Instance.Log($"Successfully removed {comArgs[1]} from the song list", exitAfterPrint);
                            }
                            else
                            {
                                Logger.Instance.Warning($"{comArgs[1]} is not in the song list", exitAfterPrint);
                            }
                        }
                        else
                        {
                            Logger.Instance.Warning($"Command usage: songs [add/remove/start/list] [songID on BeatSaver]", exitAfterPrint);
                        }
                    }
                    break;

                    case "list":
                    {
                        if (exitAfterPrint)
                        {
                            foreach (var com in Settings.Instance.AvailableSongs.Songs)
                            {
                                s += $"{Environment.NewLine}> {com}";
                            }
                        }
                        else
                        {
                            foreach (var com in availableSongs)
                            {
                                s += $"{Environment.NewLine}> {com.beatSaverId}: {com.authorName} - {com.songName} {com.songSubName}";
                            }
                        }

                        Logger.Instance.Log($"Songs:{s}", exitAfterPrint);
                    }; break;

                    case "start":
                    {
                        if (!exitAfterPrint && serverState != ServerState.Playing && currentSongIndex == -1)
                        {
                            string songId = comArgs[1];
                            if (comArgs.Length == 2 && !comArgs[1].IsNullOrEmpty())
                            {
                                currentSongIndex = availableSongs.FindIndex(x => x.beatSaverId == songId);
                                SendToAllClients(new ServerCommand(
                                                     ServerCommandType.SetSelectedSong,
                                                     _difficulty: GetPreferredDifficulty(availableSongs[currentSongIndex])), wss);
                                Logger.Instance.Log($"Next song is {availableSongs[currentSongIndex].songName} {availableSongs[currentSongIndex].songSubName}");
                            }
                            else
                            {
                                Logger.Instance.Warning($"Command usage: songs [add/remove/start/list] [songID on BeatSaver]", exitAfterPrint);
                            }
                        }
                    }; break;

                    default:
                    {
                        Logger.Instance.Warning($"Command usage: songs [add/remove/start/list] [songID on BeatSaver]", exitAfterPrint);
                    }
                    break;
                    }
                }
                else
                {
                    Logger.Instance.Warning($"Command usage: songs [add/remove/start/list] [songID on BeatSaver]", exitAfterPrint);
                }
            }; break;

            case "crash":
                throw new Exception("DebugException");
            }

            if (exitAfterPrint)
            {
                Environment.Exit(0);
            }
        }