public override async Task PlaytestFifteenMinuteTask(RconService rconService, SrcdsLogService srcdsLogService) { await base.PlaytestFifteenMinuteTask(rconService, srcdsLogService); if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("TF2 class PlaytestFifteenMinuteTask", false, color: LOG_COLOR); } var embed = new EmbedBuilder() .WithAuthor($"Setting up test server for {CleanedTitle}") .WithTitle("Workshop Link") .WithUrl(WorkshopLink.ToString()) .WithThumbnailUrl(CanUseGallery ? GalleryImages[0] : _dataService.RSettings.General.FallbackTestImageUrl) .WithDescription( $"{DatabaseUtil.GetTestServer(ServerLocation).Description}" + $"\n{Description}") .WithColor(new Color(51, 100, 173)); embed.AddField("Connect To", $"`connect {ServerLocation}; password {_dataService.RSettings.General.CasualPassword}`"); await rconService.RconCommand(ServerLocation, $"exec {_dataService.RSettings.General.PostgameConfig}"); await TestingChannel.SendMessageAsync(embed : embed.Build()); }
public override async Task PlaytestCommandPre(bool replyInContext, SrcdsLogService srcdsLogService, RconService rconService) { await base.PlaytestCommandPre(replyInContext, srcdsLogService, rconService); if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("CSGO class PlaytestCommandPre", false, color: LOG_COLOR); } var config = IsCasual ? _dataService.RSettings.General.CSGOCasualConfig : _dataService.RSettings.General.CSGOCompConfig; await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, $"exec {config}"); await Task.Delay(1000); await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, $"host_workshop_map {PlaytestCommandInfo.WorkshopId}"); _ = Task.Run(async() => { //Wait some, reset password await Task.Delay(10000); if (!IsCasual) { await rconService.RconCommand(ServerLocation, $"sv_password {CompPassword}"); } }); PlaytestCommandRunning = false; }
public virtual async Task PlaytestFifteenMinuteTask(RconService rconService, SrcdsLogService srcdsLogService) { if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("Base class PlaytestFifteenMinuteTask", false, color: LOG_COLOR); } _dataService.SetIncludePlayerCount(true); //Ensure server is awake and RCON connection is established. Run other things while waking server _ = rconService.WakeRconServer(ServerLocation); //Get rid of the old log file if one exists. Just scrap it. srcdsLogService.RemoveFeedbackFile(server); //Make a feedback file var logResult = srcdsLogService.CreateFeedbackFile(server, GetFeedbackFileName()); if (logResult) { await _log.LogMessage($"Log file created: {GetFeedbackFileName()}"); var fbf = srcdsLogService.GetFeedbackFile(server); await fbf.LogFeedback($"Pre-test feedback started at: {DateTime.Now} CT"); } }
public ReservationService(DataService data, LogHandler log, Random random, DiscordSocketClient client, SrcdsLogService srcdsLogService) { _srcdsLogService = srcdsLogService; _dataService = data; _log = log; _client = client; CanReserve = true; }
public override async Task PlaytestStartingTask(RconService rconService, SrcdsLogService srcdsLogService, AnnouncementMessage announcementMessage) { await base.PlaytestStartingTask(rconService, srcdsLogService, announcementMessage); if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("TF2 class PlaytestStartingTask", false, color: LOG_COLOR); } }
public override async Task PlaytestTwentyMinuteTask(RconService rconService, SrcdsLogService srcdsLogService) { await base.PlaytestTwentyMinuteTask(rconService, srcdsLogService); if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("CSGO class PlaytestTwentyMinuteTask", false, color: LOG_COLOR); } var wsId = GeneralUtil.GetWorkshopIdFromFqdn(WorkshopLink.ToString()); await rconService.RconCommand(ServerLocation, $"host_workshop_map {wsId}"); if (!IsCasual) { //Delay before setting password again. await Task.Delay(15000); await rconService.RconCommand(ServerLocation, $"sv_password {CompPassword}"); } //Run a loop to validate that the level has actually changed. _ = Task.Run(async() => { var tries = 0; //Loop until timeout, or success while (tries < 10) { //Wait before retry await Task.Delay(30 * 1000); var runningLevel = await rconService.GetRunningLevelAsync(ServerLocation); if (runningLevel != null && runningLevel.Length == 3 && runningLevel[1] == wsId) { break; } tries++; await _log.LogMessage($"Level not set after {tries} attempts. Trying again.", color: LOG_COLOR); await rconService.RconCommand(ServerLocation, $"host_workshop_map {wsId}"); } if (tries <= 10) { await _log.LogMessage($"Level changed after {tries} attempts!", color: LOG_COLOR); } else { await _log.LogMessage($"Failed to change level after {tries} attempts!", color: LOG_COLOR); } }); }
public override async Task PlaytestTwentyMinuteTask(RconService rconService, SrcdsLogService srcdsLogService) { await base.PlaytestTwentyMinuteTask(rconService, srcdsLogService); if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("TF2 class PlaytestTwentyMinuteTask", false, color: LOG_COLOR); } var wsId = GeneralUtil.GetWorkshopIdFromFqdn(WorkshopLink.ToString()); await rconService.RconCommand(ServerLocation, $"changelevel workshop/{wsId}"); }
public override async Task PlaytestFifteenMinuteTask(RconService rconService, SrcdsLogService srcdsLogService) { await base.PlaytestFifteenMinuteTask(rconService, srcdsLogService); if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("CSGO class PlaytestFifteenMinuteTask", false, color: LOG_COLOR); } var gameMode = IsCasual ? "casual" : "comp"; var embed = new EmbedBuilder() .WithAuthor($"Setting up test server for {CleanedTitle}") .WithTitle("Workshop Link") .WithUrl(WorkshopLink.ToString()) .WithThumbnailUrl(CanUseGallery ? GalleryImages[0] : _dataService.RSettings.General.FallbackTestImageUrl) .WithDescription( $"{DatabaseUtil.GetTestServer(ServerLocation).Description}" + $"\n{Description}") .WithColor(new Color(51, 100, 173)); //Set password as needed, again just in case RCON wasn't listening / server wasn't ready. if (IsCasual) { await rconService.RconCommand(ServerLocation, $"sv_password {_dataService.RSettings.General.CasualPassword}"); embed.AddField("Connect To", $"`connect {ServerLocation}; password {_dataService.RSettings.General.CasualPassword}`"); } else { await rconService.RconCommand(ServerLocation, $"sv_password {CompPassword}"); } //Delay to make sure level has actually changed await Task.Delay(10000); await rconService.RconCommand(ServerLocation, $"exec {_dataService.RSettings.General.PostgameConfig}; bot_stop 1"); await rconService.RconCommand(ServerLocation, "say No damage activated!; script_execute nodamage"); await TestingChannel.SendMessageAsync(embed : embed.Build()); }
public virtual async Task PlaytestStartingTask(RconService rconService, SrcdsLogService srcdsLogService, AnnouncementMessage announcementMessage) { if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("Base class PlaytestStartingTask", false, color: LOG_COLOR); } _ = rconService.WakeRconServer(ServerLocation); var mentionRole = TesterRole; //Handle comp or casual if (IsCasual) { await rconService.RconCommand(ServerLocation, $"sv_password {_dataService.RSettings.General.CasualPassword}"); } else { mentionRole = _dataService.CompetitiveTesterRole; } //Skip the alert. if (!_dataService.GetStartAlertStatus()) { _dataService.SetStartAlert(true); return; } var unsubInfo = Game.ToString(); if (!IsCasual) { unsubInfo = "comp"; } await TesterRole.ModifyAsync(x => { x.Mentionable = true; }); await TestingChannel.SendMessageAsync($"Heads up {mentionRole.Mention}! " + "There is a playtest starting __now__!" + $"\nType `>playtester {unsubInfo}` to stop getting {unsubInfo} playtest notifications.", embed : announcementMessage.CreatePlaytestEmbed(this, true, AnnouncementMessage.Id)); await TesterRole.ModifyAsync(x => { x.Mentionable = false; }); }
public PlaytestService(DataService data, GoogleCalendar calendar, LogHandler log, Random random, ReservationService reservationService, RconService rconService, SrcdsLogService srcdsLogService, DiscordSocketClient client) { _dataService = data; _log = log; _calendar = calendar; _reservationService = reservationService; _srcdsLogService = srcdsLogService; _client = client; _rconService = rconService; _announcementMessage = new AnnouncementMessage(_dataService, random, _log); _srcdsLogService.PostStartSetup(this); }
public override async Task PlaytestStartingTask(RconService rconService, SrcdsLogService srcdsLogService, AnnouncementMessage announcementMessage) { await base.PlaytestStartingTask(rconService, srcdsLogService, announcementMessage); if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("CSGO class PlaytestStartingTask", false, color: LOG_COLOR); } if (!IsCasual) { await rconService.RconCommand(ServerLocation, $"sv_password {CompPassword}"); } }
public override async Task PlaytestStartingInTask(RconService rconService, SrcdsLogService srcdsLogService , AnnouncementMessage announcementMessage) { await base.PlaytestStartingInTask(rconService, srcdsLogService, announcementMessage); if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("CSGO class PlaytestStartingInTask", false, color: LOG_COLOR); } var embed = new EmbedBuilder().WithAuthor(CleanedTitle) .AddField("Connect Information", $"`connect {ServerLocation}; password {CompPassword}`") .WithColor(new Color(55, 55, 165)); if (!IsCasual) { foreach (var creator in Creators) { try { var user = _dataService.GetSocketGuildUser(creator.Id); await user.AddRoleAsync(_dataService.ComptesterPlaytestCreator); } catch { } //Try to DM them connect information try { await creator.SendMessageAsync(embed : embed.Build()); } catch { } } await _dataService.CompetitiveTestingChannel.SendMessageAsync(embed : embed.Build()); await rconService.RconCommand(ServerLocation, $"sv_password {CompPassword}"); } }
public override async Task PlaytestCommandPre(bool replyInContext, SrcdsLogService srcdsLogService, RconService rconService) { if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("TF2 class PlaytestCommandPre", false, color: LOG_COLOR); } //Generic setup await base.PlaytestCommandPre(replyInContext, srcdsLogService, rconService); await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, $"exec {_dataService.RSettings.General.TF2Config}"); await Task.Delay(1000); await rconService.RconCommand(ServerLocation, $"changelevel workshop/{PlaytestCommandInfo.WorkshopId}"); PlaytestCommandRunning = false; }
public virtual async Task PlaytestTwentyMinuteTask(RconService rconService, SrcdsLogService srcdsLogService) { if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("Base class PlaytestTwentyMinuteTask", false, color: LOG_COLOR); } _dataService.SetIncludePlayerCount(true); //Ensure server is awake and RCON connection is established. await rconService.WakeRconServer(ServerLocation); try { await Moderator.SendMessageAsync($"You're running the {CleanedTitle} playtest in 20 minutes!"); } catch { //Ignored } await _log.LogMessage("Running playtesting starting in 20 minutes task...", true, color : LOG_COLOR); }
public override async Task PlaytestCommandPost(bool replyInContext, SrcdsLogService srcdsLogService, RconService rconService) { if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("TF2 class PlaytestCommandPost", false, color: LOG_COLOR); } await base.PlaytestCommandPost(replyInContext, srcdsLogService, rconService); await rconService.RconCommand(ServerLocation, $"changelevel workshop/{PlaytestCommandInfo.WorkshopId}"); await Task.Delay(15000); //Wait for map to change await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, $"sv_cheats 1; exec {_dataService.RSettings.General.PostgameConfig};sv_voiceenable 0"); await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, "mp_tournament 1"); await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, "mp_tournament_restart"); await DownloadHandler.DownloadPlaytestDemo(PlaytestCommandInfo); //TF2 Embed var embed = new EmbedBuilder() .WithAuthor($"Download playtest demo for {CleanedTitle}", _dataService.Guild.IconUrl, demoUrl) .WithThumbnailUrl(PlaytestCommandInfo.ThumbNailImage) .WithColor(new Color(243, 128, 72)) .WithDescription( $"[Download Demo Here]({demoUrl}) | [Map Images]({PlaytestCommandInfo.ImageAlbum}) | [Playtesting Information](https://www.tophattwaffle.com/playtesting/)"); await AnnouncmentChannel.SendMessageAsync(PlaytestCommandInfo.CreatorMentions, embed : embed.Build()); PlaytestCommandRunning = false; }
public virtual async Task PlaytestStartingInTask(RconService rconService, SrcdsLogService srcdsLogService, AnnouncementMessage announcementMessage) { if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("Base class PlaytestStartingInTask", false, color: LOG_COLOR); } //Ensure server is awake and RCON connection is established. Run other things while waking server _ = rconService.WakeRconServer(ServerLocation); //Start asking the server for player counts. _dataService.SetIncludePlayerCount(true); //Start asking for player counts JobManager.AddJob( async() => await rconService.GetPlayCountFromServer(ServerLocation), s => s.WithName("[QueryPlayerCount]").ToRunEvery(60).Seconds()); //Figure out how far away from start we are string countdownString = null; var countdown = StartDateTime.GetValueOrDefault().Subtract(DateTime.Now); if (StartDateTime.GetValueOrDefault().CompareTo(DateTime.Now) < 0) { countdownString = $"Started: {countdown:h\'H \'m\'M\'} ago!"; } else { countdownString = countdown.ToString("d'D 'h'H 'm'M'").TrimStart(' ', 'D', 'H', '0'); } await rconService.RconCommand(ServerLocation, "sv_cheats 0"); var mentionRole = TesterRole; //Handle comp or casual if (IsCasual) { await rconService.RconCommand(ServerLocation, $"sv_password {_dataService.RSettings.General.CasualPassword}"); } else { mentionRole = _dataService.CompetitiveTesterRole; } //Skip the alert. if (!_dataService.GetStartAlertStatus()) { _dataService.SetStartAlert(true); return; } var unsubInfo = Game.ToString(); if (!IsCasual) { unsubInfo = "comp"; } await TesterRole.ModifyAsync(x => { x.Mentionable = true; }); await TestingChannel.SendMessageAsync($"Heads up {mentionRole.Mention}! " + $"There is a playtest starting in {countdownString}." + $"\nType `>playtester {unsubInfo}` to manage {unsubInfo} playtest notifications.", embed : announcementMessage.CreatePlaytestEmbed(this, true, AnnouncementMessage.Id)); await TesterRole.ModifyAsync(x => { x.Mentionable = false; }); //DM users about their test foreach (var creator in Creators) { try { await creator.SendMessageAsync( $"Don't forget that you have a playtest for __**{CleanedTitle}**__ in __**{countdownString}**__"); } catch { //Could not DM creator about their test. } } }
public virtual async Task PlaytestCommandPost(bool replyInContext, SrcdsLogService srcdsLogService, RconService rconService) { if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("Base class PlaytestCommandPost", false, color: LOG_COLOR); } PlaytestCommandRunning = true; //Force the next alert to true _dataService.SetStartAlert(true); await _log.LogMessage("Running Playtest Post Tasks!", color : LOG_COLOR); //No context to send these messages to - default them if (!replyInContext) { await _dataService.CSGOTestingChannel.SendMessageAsync(embed : new EmbedBuilder() .WithAuthor($"Post playtest of {PlaytestCommandInfo.Title}") .WithColor(new Color(55, 55, 165)) .WithDescription($"\nOn **{PlaytestCommandInfo.ServerAddress}**" + $"\nWorkshop ID **{PlaytestCommandInfo.WorkshopId}**" + $"\nDemo Name **{PlaytestCommandInfo.DemoName}**").Build()); } var fbf = srcdsLogService.GetFeedbackFile(server); if (fbf != null && File.Exists(fbf.FileName)) { Directory.CreateDirectory( $"{_dataService.RSettings.ProgramSettings.PlaytestDemoPath}\\{PlaytestCommandInfo.StartDateTime:yyyy}" + $"\\{PlaytestCommandInfo.StartDateTime:MM} - {PlaytestCommandInfo.StartDateTime:MMMM}" + $"\\{PlaytestCommandInfo.DemoName}"); File.Copy(fbf.FileName, $"{_dataService.RSettings.ProgramSettings.PlaytestDemoPath}\\{PlaytestCommandInfo.StartDateTime:yyyy}" + $"\\{PlaytestCommandInfo.StartDateTime:MM} - {PlaytestCommandInfo.StartDateTime:MMMM}" + $"\\{PlaytestCommandInfo.DemoName}\\{PlaytestCommandInfo.DemoName}.txt" , true); await AnnouncmentChannel.SendFileAsync(fbf.FileName, ""); } _ = Task.Run(async() => { await Task.Delay(35000); var patreonUsers = _dataService.PatreonsRole.Members.ToArray(); GeneralUtil.Shuffle(patreonUsers); var thanks = ""; foreach (var patreonsRoleMember in patreonUsers) { thanks += $"{patreonsRoleMember.Username}, "; } await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, $"say Thanks to these supporters: {thanks.TrimEnd(',', ' ')}"); await Task.Delay(2000); await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, @"Say Become a supporter at www.patreon.com/tophattwaffle"); }); //Stop getting more feedback srcdsLogService.RemoveFeedbackFile(server); }
public virtual async Task PlaytestCommandPre(bool replyInContext, SrcdsLogService srcdsLogService, RconService rconService) { if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("Base class PlaytestCommandPre", false, color: LOG_COLOR); } PlaytestCommandRunning = true; _dataService.SetStartAlert(false); await _log.LogMessage("Running Playtest Pre Tasks!", color : LOG_COLOR); //Store test information for later use. Will be written to the DB. var gameMode = IsCasual ? "casual" : "comp"; string mentions = null; Creators.ForEach(x => mentions += $"{x.Mention} "); PlaytestCommandInfo = new PlaytestCommandInfo { Id = 1, //Only storing 1 of these in the DB at a time, so hard code to 1. Mode = gameMode, DemoName = $"{StartDateTime:MM_dd_yyyy}" + $"_{CleanedTitle.Substring(0, CleanedTitle.IndexOf(' ')).Trim()}" + $"_{gameMode}", WorkshopId = GeneralUtil.GetWorkshopIdFromFqdn(WorkshopLink.ToString()), ServerAddress = ServerLocation, Title = CleanedTitle, ThumbNailImage = CanUseGallery ? GalleryImages[0] : _dataService.RSettings.General.FallbackTestImageUrl, ImageAlbum = ImageGallery.ToString(), CreatorMentions = mentions, StartDateTime = StartDateTime.GetValueOrDefault(), Game = Game.ToString() }; var fbf = srcdsLogService.GetFeedbackFile(server); //If somehow the session does not exist... if (fbf == null) { srcdsLogService.CreateFeedbackFile(server, GetFeedbackFileName()); fbf = srcdsLogService.GetFeedbackFile(server); } await fbf.LogFeedback($"Playtest starting feedback started at: {DateTime.Now} CT"); //Write to the DB so we can restore this info next boot DatabaseUtil.StorePlaytestCommandInfo(PlaytestCommandInfo); //Figure out where to send the no context message //No context to send these messages to - default them if (!replyInContext) { await TestingChannel.SendMessageAsync(embed : new EmbedBuilder() .WithAuthor($"Pre-start playtest of {CleanedTitle}") .WithColor(new Color(55, 55, 165)) .WithDescription($"\nOn **{PlaytestCommandInfo.ServerAddress}**" + $"\nWith config of **{PlaytestCommandInfo.Mode}**" + $"\nWorkshop ID **{PlaytestCommandInfo.WorkshopId}**").Build()); } }
public override async Task PlaytestCommandPost(bool replyInContext, SrcdsLogService srcdsLogService, RconService rconService) { await base.PlaytestCommandPost(replyInContext, srcdsLogService, rconService); if (_dataService.RSettings.ProgramSettings.Debug) { _ = _log.LogMessage("CSGO class PlaytestCommandPost", false, color: LOG_COLOR); } //Fire and forget all of this. _ = Task.Run(async() => { await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, $"host_workshop_map {PlaytestCommandInfo.WorkshopId}"); await Task.Delay(15000); //Wait for map to change await rconService.RconCommand(PlaytestCommandInfo.ServerAddress, $"sv_cheats 1; bot_stop 1;exec {_dataService.RSettings.General.PostgameConfig};sv_voiceenable 0"); if (!IsCasual) { await rconService.RconCommand(ServerLocation, $"sv_password {CompPassword}"); } //Display ingame notification for in game voice and make it stick for a while. _ = Task.Run(async() => { for (var i = 0; i < 4; i++) { _ = rconService.RconCommand(PlaytestCommandInfo.ServerAddress, "script ScriptPrintMessageCenterAll(\"Please join the level testing voice channel for feedback!\");", false); await Task.Delay(3000); } }); //Enable the no damage script, cause Thomas is a real one. _ = Task.Run(async() => { //Short delay to ensure that mp_restart game already happened. await Task.Delay(5000); _ = rconService.RconCommand(PlaytestCommandInfo.ServerAddress, "say No damage activated!; script_execute nodamage"); }); var demoPath = await DownloadHandler.DownloadPlaytestDemo(PlaytestCommandInfo); FileInfo jasonFile = null; try { jasonFile = DemoParser.ParseDemo(Path.GetDirectoryName(demoPath)); } catch (Exception e) { Console.WriteLine("JIMCODE\nJIMCODE\nJIMCODE\nJIMCODE\nJIMCODE\nJIMCODE\nJIMCODE\nJIMCODE\n" + e.Message); } _ = Task.Run(async() => { foreach (var creator in Creators) { try { var user = _dataService.GetSocketGuildUser(creator.Id); await user.RemoveRoleAsync(_dataService.ComptesterPlaytestCreator); } catch { } } }); var embed = new EmbedBuilder() .WithAuthor($"Download playtest demo for {CleanedTitle}", _dataService.Guild.IconUrl, demoUrl) .WithThumbnailUrl(PlaytestCommandInfo.ThumbNailImage) .WithColor(new Color(243, 128, 72)) .WithDescription( $"[Download Demo Here]({demoUrl}) | [Map Images]({PlaytestCommandInfo.ImageAlbum}) | [Playtesting Information](https://www.tophattwaffle.com/playtesting/)"); if (jasonFile != null) { embed.AddField("Analyzed Demo", $"[View Processed Demo Here!]({demoSiteUrlBase}{jasonFile.Name.Replace(jasonFile.Extension, "")})"); } await AnnouncmentChannel.SendMessageAsync(PlaytestCommandInfo.CreatorMentions, embed: embed.Build()); PlaytestCommandRunning = false; }); }