public async Task StartCountdown(ArkServerContext serverContext, string reason, int delayInMinutes, Func <Task> react = null) { await serverContext.Steam.SendRconCommand($"serverchat Countdown started: {reason} in {delayInMinutes} minute{(delayInMinutes > 1 ? "s" : "")}..."); if (!string.IsNullOrWhiteSpace(_config.AnnouncementChannel)) { await _discordManager.SendTextMessageToChannelNameOnAllServers(_config.AnnouncementChannel, $"**Countdown started: {reason} in {delayInMinutes} minute{(delayInMinutes > 1 ? "s" : "")}...**"); } foreach (var min in Enumerable.Range(1, delayInMinutes)) { AddTimedTask(new TimedTask { When = DateTime.Now.AddMinutes(min), Callback = new Func <Task>(async() => { var countdown = delayInMinutes - min; await serverContext.Steam.SendRconCommand(countdown > 0 ? $"serverchat {reason} in {countdown} minute{(countdown > 1 ? "s" : "")}..." : $"serverchat {reason}..."); if (!string.IsNullOrWhiteSpace(_config.AnnouncementChannel)) { await _discordManager.SendTextMessageToChannelNameOnAllServers(_config.AnnouncementChannel, countdown > 0 ? $"**{reason} in {countdown} minute{(countdown > 1 ? "s" : "")}...**" : $"**{reason}...**"); } if (countdown <= 0 && react != null) { await react(); } }) }); } }
public static async Task <InitiateVoteResult> Initiate(Channel channel, ArkServerContext context, IConfig config, IEfDatabaseContext db, ulong userId, string identifier, DateTime when, string reason) { var votes = db.Votes.OfType <DestroyWildDinosVote>().Where(x => x.Result == VoteResult.Undecided).ToArray(); if (votes.Length > 0) { await channel.SendMessageDirectedAt(userId, $"there is already an active vote to wipe wild dinos."); return(null); } //proceed to initiate vote var vote = new DestroyWildDinosVote { Reason = reason, Started = when, #if DEBUG Finished = when.AddSeconds(10), #else Finished = when.AddMinutes(5), #endif Result = VoteResult.Undecided, ServerKey = context.Config.Key, Identifier = identifier }; return(new InitiateVoteResult { MessageInitiator = $"the vote to wipe wild dinos have been initiated. Announcement will be made.", MessageAnnouncement = $@"**A vote to wipe wild dinos on server ({context.Config.Key}) due to ""{reason}"" have been started. Please cast your vote in the next five minutes!**{Environment.NewLine}To vote use the command: **!vote {identifier} yes**/**no**", MessageRcon = $@"A vote to wipe wild dinos due to ""{reason}"" have been started. Please cast your vote on Discord using !vote {identifier} yes/no in the next five minutes!", Vote = vote }); }
internal static PlayerServerViewModel BuildViewModelForTransferedPlayer(ArkServerContext context, string steamId, ulong[] playerIds) { if (playerIds == null || playerIds.Length == 0) { return(null); } //there will be no player profile so most data cannot be set //a tribe where the player is a member may exist tho var tribe = context.Tribes?.FirstOrDefault(x => playerIds.Any(y => x.MemberIds.Contains((int)y))); if (tribe == null) { return(null); } var playerId = playerIds.First(x => tribe.MemberIds.Contains((int)x)); var vm = new PlayerServerViewModel { ClusterKey = context.Config.Key, SteamId = steamId, TribeId = tribe.Id, TribeName = tribe.Name, SavedAt = tribe.SavedAt }; vm.Creatures.AddRange(BuildCreatureViewModelsForPlayerId(context, playerId)); return(vm); }
private void _contextManager_VoteInitiated(ArkServerContext serverContext, VoteInitiatedEventArgs args) { if (args == null || args.Item == null) { return; } var handler = GetVoteHandler(args.Item); if (handler == null) { return; } //reminder, one minute before expiry var reminderAt = args.Item.Finished.AddMinutes(-1); if (DateTime.Now < reminderAt) { _scheduledTasksManager.AddTimedTask(new TimedTask { When = reminderAt, Tag = "vote_" + args.Item.Id, Callback = new Func <Task>(async() => { var result = handler.VoteIsAboutToExpire(); if (result == null) { return; } if (result.MessageRcon != null) { await serverContext.Steam.SendRconCommand($"serverchat {result.MessageRcon.ReplaceRconSpecialChars()}"); } if (result.MessageAnnouncement != null && !string.IsNullOrWhiteSpace(_config.Discord.AnnouncementChannel)) { await _discordManager.SendTextMessageToChannelNameOnAllServers(_config.Discord.AnnouncementChannel, result.MessageAnnouncement); } }) }); } //on elapsed _scheduledTasksManager.AddTimedTask(new TimedTask { When = args.Item.Finished, Tag = "vote_" + args.Item.Id, Callback = new Func <Task>(async() => { using (var db = _databaseContextFactory.Create()) { var vote = db.Votes.FirstOrDefault(x => x.Id == args.Item.Id); await VoteFinished(serverContext, db, vote); } }) }); }
private async Task VoteFinished(ArkServerContext serverContext, IEfDatabaseContext db, Database.Model.Vote vote, bool noAnnouncement = false, VoteResult?forcedResult = null) { var handler = GetVoteHandler(vote); if (handler == null) { return; } var votesFor = vote.Votes.Count(x => x.VotedFor); var votesAgainst = vote.Votes.Count(x => !x.VotedFor); #if DEBUG vote.Result = forcedResult ?? (vote.Votes.Count >= 1 && votesFor > votesAgainst ? VoteResult.Passed : VoteResult.Failed); #else vote.Result = forcedResult ?? (vote.Votes.Count >= 3 && votesFor > votesAgainst ? VoteResult.Passed : VoteResult.Failed); #endif VoteStateChangeResult result = null; try { result = await handler.VoteFinished(serverContext, _config, _constants, db); try { if (!noAnnouncement && result != null) { if (result.MessageRcon != null) { await serverContext.Steam.SendRconCommand($"serverchat {result.MessageRcon.ReplaceRconSpecialChars()}"); } if (result.MessageAnnouncement != null && !string.IsNullOrWhiteSpace(_config.Discord.AnnouncementChannel)) { await _discordManager.SendTextMessageToChannelNameOnAllServers(_config.Discord.AnnouncementChannel, result.MessageAnnouncement); } } } catch { /* ignore all exceptions */ } if (result != null && result.React != null) { if (result.ReactDelayInMinutes <= 0) { await result.React(); } else { await _scheduledTasksManager.StartCountdown(serverContext, result.ReactDelayFor, result.ReactDelayInMinutes, result.React); } } } catch (Exception ex) { //todo: better exception handling structure Logging.LogException(ex.Message, ex, GetType(), LogLevel.ERROR, ExceptionLevel.Unhandled); } db.SaveChanges(); }
public ArkSaveFileWatcher(ArkServerContext serverContext) { _serverContext = serverContext; _watcher = new FileSystemWatcher(); _watcher.Changed += _watcher_Changed; _watcher.Created += _watcher_Changed; SaveFilePath = serverContext.Config.SaveFilePath; }
public async Task StartCountdown(ArkServerContext serverContext, string reason, int delayInMinutes, Func <Task> react = null) { // collection of servers that should receive notifications via rcon for this countdown event var serverContexts = serverContext == null?_contextManager.Servers.Where(x => !x.Config.DisableChatNotifications).ToArray() : new ArkServerContext[] { serverContext }; foreach (var sc in serverContexts) { await sc.Steam.SendRconCommand($"serverchat Countdown started: {reason} in {delayInMinutes} minute{(delayInMinutes > 1 ? "s" : "")}..."); } if (!string.IsNullOrWhiteSpace(_config.Discord.AnnouncementChannel)) { await _discordManager.SendTextMessageToChannelNameOnAllServers(_config.Discord.AnnouncementChannel, $"**Countdown{(serverContext == null ? "" : $" on server {serverContext.Config.Key}")} started: {reason} in {delayInMinutes} minute{(delayInMinutes > 1 ? "s" : "")}...**");
private async void _contextManager_VoteResultForced(ArkServerContext sender, VoteResultForcedEventArgs args) { if (args == null || args.Item == null) { return; } _scheduledTasksManager.RemoveTimedTaskByTag("vote_" + args.Item.Id); using (var db = _databaseContextFactory.Create()) { var vote = db.Votes.FirstOrDefault(x => x.Id == args.Item.Id); await VoteFinished(sender, db, vote, forcedResult : args.Result); } }
public async Task <VoteStateChangeResult> VoteFinished(ArkServerContext serverContext, IConfig config, IConstants constants, IEfDatabaseContext db) { if (_vote == null) { return(null); } if (_vote.Result == VoteResult.Passed) { await serverContext.Steam.SendRconCommand($"settimeofday {_vote.TimeOfDay}"); } return(new VoteStateChangeResult { MessageAnnouncement = $@"{(_vote.Result == VoteResult.Passed ? ":white_check_mark:" : ":x:")} **Vote to set time of day on server ({_vote.ServerKey}) to {_vote.TimeOfDay} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}**", MessageRcon = $@"Vote to set time of day to {_vote.TimeOfDay} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}." }); }
public static async Task <InitiateVoteResult> Initiate(Channel channel, ArkServerContext context, IConfig config, IEfDatabaseContext db, ulong userId, string identifier, DateTime when, string reason, string timeOfDayRaw) { var _rTimeOfDay = new Regex(@"^\s*\d{2,2}\:\d{2,2}(\:\d{2,2})?\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (!_rTimeOfDay.IsMatch(timeOfDayRaw)) { await channel.SendMessageDirectedAt(userId, $"time of day format is invalid."); return(null); } var votes = db.Votes.OfType <SetTimeOfDayVote>().Where(x => x.Result == VoteResult.Undecided).ToArray(); if (votes.Length > 0) { await channel.SendMessageDirectedAt(userId, $"there is already an active vote to set the time of day."); return(null); } //proceed to initiate vote var vote = new SetTimeOfDayVote { TimeOfDay = timeOfDayRaw.Trim(), Reason = reason, Started = when, #if DEBUG Finished = when.AddSeconds(10), #else Finished = when.AddMinutes(2), #endif Result = VoteResult.Undecided, ServerKey = context.Config.Key, Identifier = identifier }; return(new InitiateVoteResult { MessageInitiator = $"the vote to set time of day to {vote.TimeOfDay} have been initiated. Announcement will be made.", MessageAnnouncement = $@"**A vote to set time of day on server ({context.Config.Key}) to {vote.TimeOfDay} due to ""{reason}"" have been started. Please cast your vote in the next two minutes!**{Environment.NewLine}To vote use the command: **!vote {identifier} yes**/**no**", MessageRcon = $@"A vote to set time of day to {vote.TimeOfDay} due to ""{reason}"" have been started. Please cast your vote on Discord using !vote {identifier} yes/no in the next two minutes!", Vote = vote }); }
public async Task <VoteStateChangeResult> VoteFinished(ArkServerContext serverContext, IConfig config, IConstants constants, IEfDatabaseContext db) { if (_vote == null) { return(null); } if (_vote.Result == VoteResult.Passed) { _vote.BannedUntil = _vote.Started.AddHours(_vote.DurationInHours); await serverContext.Steam.SendRconCommand($"banplayer {_vote.SteamId}"); } return(new VoteStateChangeResult { MessageAnnouncement = $@"{(_vote.Result == VoteResult.Passed ? ":white_check_mark:" : ":x:")} **Vote to ban {_vote.FullName} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}**", MessageRcon = $@"Vote to ban {_vote.FullName} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}." }); }
internal static List <CropPlotViewModel> BuildCropPlotViewModelsForPlayerId(ArkServerContext context, int playerId) { var player = context.Players?.FirstOrDefault(x => x.Id == playerId); var tribe = player != null ? player.Tribe : context.Tribes?.FirstOrDefault(x => x.MemberIds.Contains(playerId)); var cropPlots = new[] { player?.Structures, tribe?.Structures }.Where(x => x != null).SelectMany(x => x).OfType <ArkStructureCropPlot>().Where(x => x.PlantedCropClassName != null).ToArray(); var results = cropPlots.Select(x => { return(new CropPlotViewModel(x.Location) { ClassName = x.ClassName, FertilizerQuantity = (int)Math.Round(GetFertilizerQuantityFromItems(x.Inventory), 0), WaterAmount = x.WaterAmount, PlantedCropClassName = x.PlantedCropClassName, PlantedCropName = ArkItems.Instance.Data?.GetItem(x.PlantedCropClassName, structuresPlusHack: true)?.Name?.Replace(" Seed", "") ?? x.PlantedCropClassName }); }).OrderBy(x => x.Latitude).ThenBy(x => x.Longitude).ToList(); return(results); }
internal static PlayerServerViewModel BuildViewModelForPlayer(ArkServerContext context, ArkPlayer player) { var vm = new PlayerServerViewModel { ClusterKey = context.Config.Key, SteamId = player.SteamId, CharacterName = player.CharacterName, Gender = player.Gender.ToString(), Level = player.CharacterLevel, Latitude = player.Location?.Latitude, Longitude = player.Location?.Longitude, TopoMapX = player.Location?.TopoMapX, TopoMapY = player.Location?.TopoMapY, EngramPoints = player.TotalEngramPoints, TribeId = player.TribeId, TribeName = player.TribeId.HasValue ? context.Tribes.FirstOrDefault(x => x.Id == player.TribeId.Value)?.Name : null, SavedAt = player.SavedAt }; vm.Creatures.AddRange(BuildCreatureViewModelsForPlayerId(context, player.Id)); return(vm); }
public async Task <VoteStateChangeResult> VoteFinished(ArkServerContext serverContext, IConfig config, IConstants constants, IEfDatabaseContext db) { if (_vote == null) { return(null); } return(new VoteStateChangeResult { MessageAnnouncement = $@"{(_vote.Result == VoteResult.Passed ? ":white_check_mark:" : ":x:")} **Vote to update the server ({_vote.ServerKey}) have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}**", MessageRcon = $@"Vote to update the server have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}.", ReactDelayInMinutes = 5, ReactDelayFor = "Server update", React = _vote.Result == VoteResult.Passed ? new Func <Task>(async() => { string message = null; if (!await _arkServerService.UpdateServer(_vote.ServerKey, (s) => { message = s; return Task.FromResult((IUserMessage)null); }, (s) => s.FirstCharToUpper(), 300)) { Logging.Log($@"Vote to update server ({_vote.ServerKey}) execution failed (""{message ?? ""}"")", GetType(), LogLevel.DEBUG); } }) : null }); }
public async Task <VoteStateChangeResult> VoteFinished(ArkServerContext serverContext, IConfig config, IConstants constants, IEfDatabaseContext db) { if (_vote == null) { return(null); } if (_vote.Result == VoteResult.Passed) { var bans = db.Votes.OfType <BanVote>().Where(x => x.SteamId == _vote.SteamId && x.Result == VoteResult.Passed && x.BannedUntil.HasValue && x.BannedUntil.Value > DateTime.Now); foreach (var ban in bans) { ban.BannedUntil = null; } await serverContext.Steam.SendRconCommand($"unbanplayer {_vote.SteamId}"); } return(new VoteStateChangeResult { MessageAnnouncement = $@"{(_vote.Result == VoteResult.Passed ? ":white_check_mark:" : ":x:")} **Vote to unban {_vote.FullName} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}**", MessageRcon = $@"Vote to unban {_vote.FullName} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}." }); }
internal static PlayerServerViewModel BuildViewModelForTransferedPlayer( ArkServerContext context, IConfig config, string steamId, int[] playerIds, DemoMode demoMode, bool incProfile, bool incProfileDetailed, bool incCreatures, bool incCreaturesBaseStats, bool incCreaturesCloud, bool incCrops, bool incGenerators, bool incKibblesEggs, bool incTribeLog) { if (playerIds == null || playerIds.Length == 0) { return(null); } //there will be no player profile so most data cannot be set //a tribe where the player is a member may exist tho //note: potentially there could be multiple tribes with the same player, which player.Tribe protects us against. here we just select the first one which is not optimal var tribe = context.Tribes?.FirstOrDefault(x => playerIds.Any(y => x.MemberIds.Contains(y))); if (tribe == null) { return(null); } var playerId = playerIds.First(x => tribe.MemberIds.Contains(x)); var vm = new PlayerServerViewModel { ClusterKey = context.Config.Key, SteamId = steamId, TribeId = tribe.Id, TribeName = demoMode?.GetTribeName(tribe.Id) ?? tribe.Name, SavedAt = tribe.SavedAt }; if (demoMode != null) { vm.FakeSteamId = demoMode.GetSteamId(steamId); } if (incCreatures) { vm.Creatures.AddRange(BuildCreatureViewModelsForPlayerId(context, config, playerId, demoMode, incCreaturesBaseStats)); } if (incKibblesEggs) { vm.KibblesAndEggs = BuildKibblesAndEggsViewModelsForPlayerId(context, playerId); } if (incCrops) { vm.CropPlots = BuildCropPlotViewModelsForPlayerId(context, playerId); } if (incGenerators) { vm.Generators = BuildGeneratorViewModelsForPlayerId(context, playerId); } if (incTribeLog) { vm.TribeLog = BuildTribeLogViewModelsForPlayerId(context, playerId, config.WebApp.TribeLogLimit, config.WebApp.TribeLogColors); } return(vm); }
public static async Task <InitiateVoteResult> Initiate(Channel channel, ArkServerContext context, IConfig config, IEfDatabaseContext db, ulong userId, string identifier, DateTime when, string reason, string targetRaw, int durationInHours) { var _rId = new Regex(@"^\s*(id|(steam\s*id))\s*\:\s*(?<id>\d+)\s*$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.ExplicitCapture); var m = _rId.Match(targetRaw); var targets = m.Success ? context.Players.Where(x => x.Id.ToString().Equals(m.Groups["id"].Value) || x.SteamId.Equals(m.Groups["id"].Value)).ToArray() : context.Players.Where(x => (x.Name != null && x.Name.Equals(targetRaw, StringComparison.OrdinalIgnoreCase)) || (x.Name != null && x.Name.Equals(targetRaw, StringComparison.OrdinalIgnoreCase))).ToArray(); if (targets.Length == 0) { await channel.SendMessageDirectedAt(userId, $"could not find a player with that name (maybe they have not been saved yet?). Try using their steam id instead."); return(null); } if (targets.Length > 1) { await channel.SendMessageDirectedAt(userId, $"there are more than one player with that name. Try using their steam id instead."); return(null); } var target = targets.First(); var steamId = long.Parse(target.SteamId); var votes = db.Votes.OfType <BanVote>().Where(x => x.SteamId == steamId).ToArray(); if (votes.Any(x => x.BannedUntil.HasValue && x.BannedUntil.Value > when)) { await channel.SendMessageDirectedAt(userId, $"this player is already banned."); return(null); } var unvotes = db.Votes.OfType <UnbanVote>().Where(x => x.SteamId == steamId).ToArray(); if (votes.Any(x => x.Result == VoteResult.Undecided) || unvotes.Any(x => x.Result == VoteResult.Undecided)) { await channel.SendMessageDirectedAt(userId, $"there is already an active vote to ban/unban this player."); return(null); } //proceed to initiate vote var vote = new BanVote { SteamId = steamId, PlayerName = target.Name, CharacterName = target.Name, TribeName = target.TribeId.HasValue ? context.Tribes?.FirstOrDefault(x => x.Id == target.TribeId)?.Name : null, //target.TribeName, Reason = reason, Started = when, #if DEBUG Finished = when.AddSeconds(10), #else Finished = when.AddMinutes(5), #endif DurationInHours = durationInHours, Result = VoteResult.Undecided, ServerKey = context.Config.Key, Identifier = identifier }; return(new InitiateVoteResult { MessageInitiator = $"the vote to ban this player have been initiated. Announcement will be made.", MessageAnnouncement = $@"**A vote to ban {vote.FullName}{(vote.DurationInHours <= (24 * 90) ? $" for {vote.DurationInHours}h" : "")} due to ""{reason}"" have been started. Please cast your vote in the next five minutes!**{Environment.NewLine}To vote use the command: **!vote {identifier} yes**/**no**", MessageRcon = $@"A vote to ban {vote.FullName}{(vote.DurationInHours <= (24 * 90) ? $" for {vote.DurationInHours}h" : "")} due to ""{reason}"" have been started. Please cast your vote on Discord using !vote {identifier} yes/no in the next five minutes!", Vote = vote }); }
//todo: this method does not really belong here and should be moved elsewhere public static async Task <ArkSavegameToolkitNet.Domain.ArkPlayer> GetCurrentPlayerOrSendErrorMessage(CommandEventArgs e, EfDatabaseContextFactory databaseContextFactory, ArkServerContext serverContext) { using (var db = databaseContextFactory.Create()) { var user = db.Users.FirstOrDefault(x => x.DiscordId == (long)e.User.Id && !x.Unlinked); if (user == null) { await e.Channel.SendMessage($"<@{e.User.Id}>, this command can only be used after you link your Discord user with your Steam account using **!linksteam**."); return(null); } var player = serverContext.Players.FirstOrDefault(x => x.SteamId != null && x.SteamId.Equals(user.SteamId.ToString())); if (player == null) { await e.Channel.SendMessage($"<@{e.User.Id}>, we have no record of you playing in the last month."); return(null); } return(player); } }
internal static List <ElectricalGeneratorViewModel> BuildElectricalGeneratorViewModelsForPlayerId(ArkServerContext context, int playerId) { var player = context.Players?.FirstOrDefault(x => x.Id == playerId); var tribe = context.Tribes?.FirstOrDefault(x => x.MemberIds.Contains(playerId)); var electricalGenerators = new[] { player?.Structures, tribe?.Structures }.Where(x => x != null).SelectMany(x => x).OfType <ArkStructureElectricGenerator>().ToArray(); var results = electricalGenerators.Select(x => { return(new ElectricalGeneratorViewModel(x.Location) { Activated = x.Activated, //FuelTime = x.FuelTime, GasolineQuantity = (int)(x.Inventory?.Where(y => y.ClassName.Equals("PrimalItemResource_Gasoline_C", StringComparison.Ordinal)).Sum(y => y.Quantity) ?? 0) }); }).OrderBy(x => x.Latitude).ThenBy(x => x.Longitude).ToList(); return(results); }
internal static List <GeneratorViewModel> BuildGeneratorViewModelsForPlayerId(ArkServerContext context, int playerId) { if (!ArkSavegameToolkitNet.ArkToolkitSettings.Instance.ObjectTypes.TryGetValue(ArkSavegameToolkitNet.ObjectType.ItemElectricGeneratorGasoline, out var classNames)) { return(new List <GeneratorViewModel>()); } var player = context.Players?.FirstOrDefault(x => x.Id == playerId); var tribe = player != null ? player.Tribe : context.Tribes?.FirstOrDefault(x => x.MemberIds.Contains(playerId)); var generators = new[] { player?.Structures, tribe?.Structures }.Where(x => x != null).SelectMany(x => x).OfType <ArkStructureElectricGenerator>().ToArray(); var results = generators.Select(x => { return(new GeneratorViewModel(x.Location) { Activated = x.Activated, //FuelTime = x.FuelTime, PrimalItemResource_Gasoline_C , PrimalItemResource_Gasoline_JStacks_C FuelQuantity = (int)(x.Inventory?.Where(y => classNames.Contains(y.ClassName, StringComparer.Ordinal)).Sum(y => y.Quantity) ?? 0) }); }).OrderBy(x => x.Latitude).ThenBy(x => x.Longitude).ToList(); return(results); }
internal static List <TribeLogEntryViewModel> BuildTribeLogViewModelsForPlayerId(ArkServerContext context, int playerId, int?limit = null, bool logColors = false) { var player = context.Players?.FirstOrDefault(x => x.Id == playerId); var tribe = player != null ? player.Tribe : context.Tribes?.FirstOrDefault(x => x.MemberIds.Contains(playerId)); var tribelogs = tribe?.Logs?.Reverse().Take(limit ?? tribe.Logs.Length).Select(x => TribeLog.FromLog(x)).ToArray() ?? new TribeLog[] { }; var results = tribelogs.Select(x => { return(new TribeLogEntryViewModel { Day = x.Day, Time = x.Time, Message = logColors ? x.MessageHtml : x.MessageUnformatted }); }).ToList(); return(results); }
internal static List <TamedCreatureViewModel> BuildCreatureViewModelsForPlayerId(ArkServerContext context, ulong playerId) { var result = new List <TamedCreatureViewModel>(); if (context.TamedCreatures != null) { var playercreatures = context.NoRafts.Where(x => (ulong)x.TargetingTeam == playerId || (x.OwningPlayerId.HasValue && (ulong)x.OwningPlayerId == playerId)).ToArray(); var tribe = context.Tribes?.FirstOrDefault(x => x.MemberIds.Contains((int)playerId)); var tribecreatures = tribe != null?context.NoRafts.Where(x => x.TargetingTeam == tribe.Id && !playercreatures.Any(y => y.Id == x.Id)).ToArray() : new ArkTamedCreature[] { }; foreach (var item in playercreatures.Select(x => new { c = x, o = "player" }).Concat(tribecreatures.Select(x => new { c = x, o = "tribe" }))) { var currentFood = item.c.CurrentStatusValues?.Length > 4 ? item.c.CurrentStatusValues[4] : null; var maxFood = item.c.BaseStats?.Length > 4 && item.c.TamedStats?.Length > 4 ? ArkContext.CalculateMaxStat( ArkSpeciesStatsData.Stat.Food, item.c.ClassName, item.c.BaseStats[4], item.c.TamedStats[4], (decimal)(item.c.DinoImprintingQuality ?? 0f), (decimal)(item.c.TamedIneffectivenessModifier ?? 0f)) : null; //baby food formula: max * 0.1 + (max - (max * 0.1)) * age if (maxFood.HasValue && item.c.BabyAge.HasValue) { maxFood = maxFood.Value * 0.1 + (maxFood.Value - (maxFood.Value * 0.1)) * item.c.BabyAge.Value; } var foodStatus = currentFood.HasValue && maxFood.HasValue ? currentFood.Value / (float)maxFood.Value : (float?)null; if (foodStatus.HasValue && foodStatus > 1f) { foodStatus = 1f; } var aliases = ArkSpeciesAliases.Instance.GetAliases(item.c.ClassName); var vmc = new TamedCreatureViewModel { Name = item.c.Name, ClassName = item.c.ClassName, Species = aliases?.FirstOrDefault(), Aliases = aliases?.Skip(2).ToArray() ?? new string[] { }, //skip primary name and class name Gender = item.c.Gender.ToString(), BaseLevel = item.c.BaseLevel, Level = item.c.Level, BabyAge = item.c.IsBaby ? item.c.BabyAge : null, Imprint = item.c.DinoImprintingQuality, FoodStatus = foodStatus, Latitude = item.c.Location?.Latitude, Longitude = item.c.Location?.Longitude, TopoMapX = item.c.Location?.TopoMapX, TopoMapY = item.c.Location?.TopoMapY, NextMating = item.c.NextAllowedMatingTimeApprox, BabyNextCuddle = item.c.BabyNextCuddleTimeApprox, OwnerType = item.o }; result.Add(vmc); } } return(result); }
internal static List <KibbleAndEggViewModel> BuildKibblesAndEggsViewModelsForPlayerId(ArkServerContext context, int playerId) { var player = context.Players?.FirstOrDefault(x => x.Id == playerId); var tribe = player != null ? player.Tribe : context.Tribes?.FirstOrDefault(x => x.MemberIds.Contains(playerId)); //PrimalItemConsumable_Egg_Kaprosuchus_C, PrimalItemConsumable_Egg_Kaprosuchus_Fertilized_C, PrimalItemConsumable_Egg_Wyvern_Fertilized_Lightning_C var _rEgg = new Regex(@"^PrimalItemConsumable_Egg_(?<name>.+?)_C$", RegexOptions.Singleline); //PrimalItemConsumable_Kibble_GalliEgg_C, PrimalItemConsumable_Kibble_Compy_C var _rKibble = new Regex(@"^PrimalItemConsumable_Kibble_(?<name>.+?)(?:Egg)?_C$", RegexOptions.IgnoreCase | RegexOptions.Singleline); var inv = new[] { player?.Items, tribe?.Items }.Where(x => x != null).SelectMany(x => x).ToArray(); var kibbles = inv.Where(x => x.ClassName.StartsWith("PrimalItemConsumable_Kibble", StringComparison.Ordinal)) .GroupBy(x => x.ClassName) .Select(x => { return(new { Name = ArkItems.Instance.Data?.GetItem(x.Key)?.Name ?? x.Key, Count = x.Sum(y => y.Quantity) }); }) .ToArray(); var eggs = inv.Where(x => x.ClassName.StartsWith("PrimalItemConsumable_Egg", StringComparison.Ordinal) && !x.ClassName.Contains("_Fertilized_")) .GroupBy(x => x.ClassName) .Select(x => { return(new { Name = ArkItems.Instance.Data?.GetItem(x.Key)?.Name ?? x.Key, Count = x.Sum(y => y.Quantity) }); }) .ToList(); var keys = kibbles.Select(x => x.Name).Concat(eggs.Select(x => x.Name)).Distinct(); var results = keys.Select(x => { var k = kibbles.FirstOrDefault(y => y.Name.Equals(x)); var e = eggs.FirstOrDefault(y => y.Name.Equals(x)); return(new KibbleAndEggViewModel { Name = k?.Name ?? e?.Name, KibbleCount = k?.Count ?? 0L, EggCount = e?.Count ?? 0L }); }).OrderByDescending(x => x.EggCount + x.KibbleCount).ToList(); return(results); }
internal static List <TamedCreatureViewModel> BuildCreatureViewModelsForPlayerId(ArkServerContext context, IConfig config, int playerId, DemoMode demoMode, bool incBaseStats = false) { var result = new List <TamedCreatureViewModel>(); if (context.TamedCreatures != null) { var player = context.Players?.FirstOrDefault(x => x.Id == playerId); var playercreatures = context.NoRafts.Where(x => x.TargetingTeam == playerId || x.OwningPlayerId.HasValue && x.OwningPlayerId == playerId).ToArray(); var playercreatures_cryo = player?.Items?.OfType <ArkItemCryopod>().Where(x => x.Dino != null).Select(x => x.Dino).ToArray() ?? new ArkTamedCreature[] { }; var tribe = player != null ? player.Tribe : context.Tribes?.FirstOrDefault(x => x.MemberIds.Contains(playerId)); var tribecreatures = tribe != null?context.NoRafts.Where(x => x.TargetingTeam == tribe.Id && !playercreatures.Any(y => y.Id == x.Id)).ToArray() : new ArkTamedCreature[] { }; var tribecreatures_cryo = tribe?.Items?.OfType <ArkItemCryopod>().Where(x => x.Dino != null).Select(x => x.Dino).ToArray() ?? new ArkTamedCreature[] { }; foreach (var item in playercreatures.Select(x => new { c = x, o = "player", cryo = false }) .Concat(playercreatures_cryo.Select(x => new { c = x, o = "player", cryo = true })) .Concat(tribecreatures.Select(x => new { c = x, o = "tribe", cryo = false })) .Concat(tribecreatures_cryo.Select(x => new { c = x, o = "tribe", cryo = true }))) { var currentFood = item.c.CurrentStatusValues?.Length > 4 ? item.c.CurrentStatusValues[4] : null; var maxFood = item.c.BaseStats?.Length > 4 && item.c.TamedStats?.Length > 4 ? ArkDataHelper.CalculateMaxStat( ArkSpeciesStatsData.Stat.Food, item.c.ClassName, true, item.c.BaseStats[4], item.c.TamedStats[4], (decimal)(item.c.DinoImprintingQuality ?? 0f), (decimal)(item.c.TamedIneffectivenessModifier ?? 0f)) : null; //baby food formula: max * 0.1 + (max - (max * 0.1)) * age if (maxFood.HasValue && item.c.BabyAge.HasValue) { maxFood = maxFood.Value * 0.1 + (maxFood.Value - maxFood.Value * 0.1) * item.c.BabyAge.Value; } var foodStatus = currentFood.HasValue && maxFood.HasValue ? currentFood.Value / (float)maxFood.Value : (float?)null; if (foodStatus.HasValue && foodStatus > 1f) { foodStatus = 1f; } //baby fully grown var babyFullyGrownTimeApprox = (DateTime?)null; if (item.c.IsBaby && item.c.BabyAge.HasValue && context.SaveState.GameTime.HasValue) { var babyFullyGrown = ArkDataHelper.CalculateBabyFullyGrown(item.c.ClassName, item.c.BabyAge.Value, context.Config.ArkMultipliers); babyFullyGrownTimeApprox = context.SaveState.GetApproxDateTimeOf(context.SaveState.GameTime.Value + babyFullyGrown); } var aliases = ArkSpeciesAliases.Instance.GetAliasesByClassName(item.c.ClassName); var vmc = new TamedCreatureViewModel { Id1 = item.c.Id1, Id2 = item.c.Id2, Name = demoMode?.GetCreatureName(item.c.Id1, item.c.Id2, aliases?.FirstOrDefault()) ?? item.c.Name, ClassName = item.c.ClassName, Species = aliases?.FirstOrDefault(), Aliases = aliases?.Skip(2).ToArray() ?? new string[] { }, //skip primary name and class name Gender = item.c.Gender.ToString(), BaseLevel = item.c.BaseLevel, Level = item.c.Level, Experience = item.c.ExperiencePoints ?? 0f, BabyAge = item.c.IsBaby ? item.c.BabyAge : null, Imprint = item.c.DinoImprintingQuality, FoodStatus = foodStatus, Latitude = item.cryo ? null : item.c.Location?.Latitude, Longitude = item.cryo ? null : item.c.Location?.Longitude, TopoMapX = item.cryo ? null : item.c.Location?.TopoMapX, TopoMapY = item.cryo ? null : item.c.Location?.TopoMapY, NextMating = !item.c.IsBaby && item.c.Gender == ArkCreatureGender.Female ? item.c.NextAllowedMatingTimeApprox : null, BabyFullyGrown = babyFullyGrownTimeApprox, BabyNextCuddle = item.c.BabyNextCuddleTimeApprox, OwnerType = item.o, InCryopod = item.cryo, Parents = item.c.DinoAncestors?.Length > 0 && item.c.DinoAncestorsMale?.Length > 0 ? new CreatureParentsViewModel { Female = new CreatureIdViewModel { Id1 = item.c.DinoAncestors.First().FemaleId1, Id2 = item.c.DinoAncestors.First().FemaleId2 }, Male = new CreatureIdViewModel { Id1 = item.c.DinoAncestorsMale.First().MaleId1, Id2 = item.c.DinoAncestorsMale.First().MaleId2 } } : null, RandomMutationsFemale = item.c.RandomMutationsFemale, RandomMutationsMale = item.c.RandomMutationsMale, }; if (incBaseStats) { //0: health //1: stamina //2: torpor //3: oxygen //4: food //5: water //6: temperature //7: weight //8: melee damage //9: movement speed //10: fortitude //11: crafting speed vmc.BaseStats = new CreatureStatsViewModel { Health = item.c.BaseStats[0], Stamina = item.c.BaseStats[1], Oxygen = item.c.BaseStats[3], Food = item.c.BaseStats[4], Weight = item.c.BaseStats[7], Melee = item.c.BaseStats[8], MovementSpeed = item.c.BaseStats[9] }; vmc.TamedStats = new CreatureStatsViewModel { Health = item.c.TamedStats[0], Stamina = item.c.TamedStats[1], Oxygen = item.c.TamedStats[3], Food = item.c.TamedStats[4], Weight = item.c.TamedStats[7], Melee = item.c.TamedStats[8], MovementSpeed = item.c.TamedStats[9] }; var statValues = ArkSpeciesStats.Instance.Data.GetStatValues(item.c); vmc.StatValues = new CreatureStatValuesViewModel { Tamed = statValues.tamed, TamedNoImprint = statValues.tamedNoImprint, Wild = statValues.wild, }; } result.Add(vmc); } } return(result); }
internal static PlayerServerViewModel BuildViewModelForTransferedPlayer( ArkServerContext context, IConfig config, string steamId, int[] playerIds, DemoMode demoMode, bool incProfile, bool incProfileDetailed, bool incCreatures, bool incCreaturesBaseStats, bool incCreaturesCloud, bool incCrops, bool incGenerators, bool incKibblesEggs, bool incTribeLog) { if (playerIds == null || playerIds.Length == 0) { return(null); } //there will be no player profile so most data cannot be set //a tribe where the player is a member may exist tho var tribe = context.Tribes?.FirstOrDefault(x => playerIds.Any(y => x.MemberIds.Contains((int)y))); if (tribe == null) { return(null); } var playerId = playerIds.First(x => tribe.MemberIds.Contains((int)x)); var vm = new PlayerServerViewModel { ClusterKey = context.Config.Key, SteamId = steamId, TribeId = tribe.Id, TribeName = demoMode?.GetTribeName(tribe.Id) ?? tribe.Name, SavedAt = tribe.SavedAt }; if (demoMode != null) { vm.FakeSteamId = demoMode.GetSteamId(steamId); } if (incCreatures) { vm.Creatures.AddRange(BuildCreatureViewModelsForPlayerId(context, config, playerId, demoMode, incCreaturesBaseStats)); } if (incKibblesEggs) { vm.KibblesAndEggs = BuildKibblesAndEggsViewModelsForPlayerId(context, playerId); } if (incCrops) { vm.CropPlots = BuildCropPlotViewModelsForPlayerId(context, playerId); } if (incGenerators) { vm.ElectricalGenerators = BuildElectricalGeneratorViewModelsForPlayerId(context, playerId); } if (incTribeLog) { vm.TribeLog = BuildTribeLogViewModelsForPlayerId(context, playerId, 100); } return(vm); }
private void ContextManager_BackupCompleted(ArkServerContext sender, bool backupsEnabled, SavegameBackupResult result) { _signaller.PulseAll(Tuple.Create(sender, backupsEnabled, result)); }
internal static PlayerServerViewModel BuildViewModelForPlayer( ArkServerContext context, IConfig config, ArkPlayer player, DemoMode demoMode, bool incProfile, bool incProfileDetailed, bool incCreatures, bool incCreaturesBaseStats, bool incCreaturesCloud, bool incCrops, bool incGenerators, bool incKibblesEggs, bool incTribeLog) { var tribe = player.Tribe; var vm = new PlayerServerViewModel { ClusterKey = context.Config.Key, SteamId = player.SteamId, FakeSteamId = demoMode?.GetSteamId(player.SteamId), CharacterName = demoMode?.GetPlayerName(player.Id) ?? player.CharacterName, TribeId = player.TribeId, TribeName = tribe != null?demoMode?.GetTribeName(tribe.Id) ?? tribe?.Name : null, SavedAt = player.SavedAt }; if (incProfileDetailed) { vm.Latitude = player.Location?.Latitude; vm.Longitude = player.Location?.Longitude; vm.TopoMapX = player.Location?.TopoMapX; vm.TopoMapY = player.Location?.TopoMapY; if (!player.IsExternalPlayer) { vm.Gender = player.Gender.ToString(); vm.Level = player.CharacterLevel; vm.EngramPoints = player.TotalEngramPoints; } } if (incCreatures) { vm.Creatures.AddRange(BuildCreatureViewModelsForPlayerId(context, config, player.Id, demoMode, incCreaturesBaseStats)); } if (incKibblesEggs) { vm.KibblesAndEggs = BuildKibblesAndEggsViewModelsForPlayerId(context, player.Id); } if (incCrops) { vm.CropPlots = BuildCropPlotViewModelsForPlayerId(context, player.Id); } if (incGenerators) { vm.Generators = BuildGeneratorViewModelsForPlayerId(context, player.Id); } if (incTribeLog) { vm.TribeLog = BuildTribeLogViewModelsForPlayerId(context, player.Id, config.WebApp.TribeLogLimit, config.WebApp.TribeLogColors); } return(vm); }
public ArkSaveFileWatcherTimer(ArkServerContext serverContext) { _serverContext = serverContext; _timer = new Timer(_timer_Callback, null, TimeSpan.Zero, _delay); }