private dynamic GetTamed(uint id1, uint id2, ArkTamedCreature tamed = null) { var result = (dynamic)_tamed.GetOrCreate(Tuple.Create(id1, id2), () => { dynamic o = new ExpandoObject(); var n = _tamedNext++; o.Id1 = (uint)(1000000 + n); o.Id2 = (uint)(1000000 + n); o.Name = tamed?.Name == null ? null : GetDinoName(tamed?.ClassName, tamed?.TargetingTeam); //o.OldName = tamed?.Name; return((ExpandoObject)o); }); return(result); }
public void Do(ArkTamedCreature i) { var anon = GetTamed(i.Id1, i.Id2, i); i.Id1 = anon.Id1; i.Id2 = anon.Id2; if (i.Name != null) { i.Name = anon.Name; } if ((i.OwningPlayerId.HasValue && i.OwningPlayerId.Value != i.TargetingTeam) || !i.OwningPlayerId.HasValue) { var tribe = GetTribe(i.TargetingTeam); i.TargetingTeam = tribe.Id; i.TribeName = tribe.Name; } else { i.TribeName = null; } if (i.OwningPlayerId.HasValue) { var owner = GetPlayer(i.OwningPlayerId.Value); i.TargetingTeam = owner.Id; i.OwningPlayerId = owner.Id; i.OwningPlayerName = owner.CharacterName; } if (i.ImprinterPlayerDataId.HasValue) { var imprinter = GetPlayer((int)i.ImprinterPlayerDataId.Value); i.ImprinterPlayerDataId = imprinter.Id; i.ImprinterName = imprinter.CharacterName; } i.TamerName = null; //can be both tribe and player i.TamedOnServerName = null; }
/// <param name="externalPlayerData">Supply the update operation with external player data. This is a way to make sure transfered players are not lost inbetween saves.</param> public ArkGameDataUpdateResult Update(CancellationToken ct, ArkPlayerExternal[] externalPlayerData = null, bool deferApplyNewData = false, ArkAnonymizeData anonymize = null) { var success = false; var cancelled = false; ArkSavegame save = null; var st = Stopwatch.StartNew(); try { var directoryPath = Path.GetDirectoryName(_saveFilePath); var exclusivePropertyNameTree = _loadOnlyPropertiesInDomain ? ArkGameDataContainerBase._alldependencies : null; // Extract all game data save = new ArkSavegame(_saveFilePath, null, _savegameMaxDegreeOfParallelism, exclusivePropertyNameTree); save.LoadEverything(); ct.ThrowIfCancellationRequested(); var arktribes = Directory.GetFiles(directoryPath, "*.arktribe", SearchOption.TopDirectoryOnly).Select(x => { try { return(new ArkSavegameToolkitNet.ArkTribe(x, exclusivePropertyNameTree: exclusivePropertyNameTree)); } catch (Exception ex) { Debug.WriteLine($"Failed to extract tribe profile '{x}': {ex.Message}"); } return(null); }).Where(x => x != null).ToArray(); ct.ThrowIfCancellationRequested(); var _myData = ArkName.Create("MyData"); var _playerDataID = ArkName.Create("PlayerDataID"); var _linkedPlayerDataID = ArkName.Create("LinkedPlayerDataID"); var _uniqueID = ArkName.Create("UniqueID"); var arkprofiles = Directory.GetFiles(directoryPath, "*.arkprofile", SearchOption.TopDirectoryOnly).Select(x => { try { return(new ArkProfile(x, exclusivePropertyNameTree: exclusivePropertyNameTree)); } catch (Exception ex) { Debug.WriteLine($"Failed to extract player profile '{x}': {ex.Message}"); } return(null); }).Where(x => x != null).ToArray(); ct.ThrowIfCancellationRequested(); // Map all game data into domain model // Note: objects.GroupBy(x => x.Names.Last().Token) would also get creature, status- and inventory component together var statusComponents = save.Objects.Where(x => x.IsDinoStatusComponent).ToDictionary(x => x.ObjectId, x => x); var tamed = save.Objects.Where(x => x.IsTamedCreature).Select(x => { GameObject status = null; statusComponents.TryGetValue(x.GetPropertyValue <ObjectReference>(_myCharacterStatusComponent).ObjectId, out status); ArkTamedCreature returnValue = x.AsTamedCreature(status, save.SaveState); return(returnValue); }).ToArray(); // Remove duplicates from object collection (objects are sometimes duplicated for structures, creatures etc.) // Had to move down as seemed to be removing genuine tames - maybe due to cryopod use? var objects = save.Objects.GroupBy(x => x.Names, new ArkNameCollectionComparer()).Select(x => x.OrderBy(y => y.ObjectId).First()).ToArray(); var wild = objects.Where(x => x.IsWildCreature).Select(x => { GameObject status = null; statusComponents.TryGetValue(x.GetPropertyValue <ObjectReference>(_myCharacterStatusComponent).ObjectId, out status); ArkWildCreature returnValue = x.AsWildCreature(status, save.SaveState); return(returnValue); }).ToArray(); var playerdict = objects.Where(x => x.IsPlayerCharacter).ToLookup(x => x.GetPropertyValue <long>(_linkedPlayerDataID), x => x); //var duplicates = playerdict.Where(x => x.Count() > 1).ToArray(); //mydata.GetPropertyValue<StructUniqueNetIdRepl>(_uniqueID)?.NetId //private static readonly ArkName _uniqueID = ArkName.Create("UniqueID"); List <Tuple <string, long, ArkProfile> > distinctProfiles = new List <Tuple <string, long, ArkProfile> >(); foreach (var x in arkprofiles) { try { var mydata = x.GetPropertyValue <StructPropertyList>(_myData); Tuple <string, long, ArkProfile> newTuple = new Tuple <string, long, ArkProfile>(mydata.GetPropertyValue <Structs.StructUniqueNetIdRepl>(_uniqueID)?.NetId, mydata.GetPropertyValue <long>(_playerDataID), x); if (distinctProfiles.Count(p => p.Item1 == newTuple.Item1) == 0) { distinctProfiles.Add(newTuple); } } catch (Exception ex) { Debug.WriteLine($"Failed to project player profile as domain object '{x._fileName}': {ex.Message}"); } } var keyedProfiles = distinctProfiles.Select(x => { return(new { steamId = x.Item1, playerId = x.Item2, profile = x.Item3, }); }).ToArray(); var profileSteamIds = keyedProfiles.Select(x => x.steamId).Where(x => x != null).Distinct(); var players = keyedProfiles.Select(x => { var player = playerdict[x.playerId]?.FirstOrDefault(); try { return(x.profile.Profile.AsPlayer(player, x.profile.SaveTime, save.SaveState)); } catch (Exception ex) { Debug.WriteLine($"Failed to project player profile as domain object '{x.profile._fileName}': {ex.Message}"); } return(null); }).Where(x => x != null).ToArray(); var externalPlayers = externalPlayerData != null? externalPlayerData.Where(x => !profileSteamIds.Contains(x.SteamId, StringComparer.OrdinalIgnoreCase)).Select(x => x.AsPlayer()).ToArray() : new ArkPlayer[] { }; var allplayers = players.Concat(externalPlayers).ToArray(); var tribes = arktribes.Select(x => x.Tribe.AsTribe(x.SaveTime)).Where(t => t.Id != 0).ToArray(); var items = objects.Where(x => x.IsItem).Select(x => x.AsItem(save.SaveState)).ToArray(); var droppedItems = objects.Where(x => x.IsDroppedItem).Select(x => { GameObject linkedItem = null; int linkedItemId = x.GetPropertyValue <ObjectReference>(ArkName.Create("MyItem")).ObjectId; linkedItem = objects.Where(o => o.ObjectId == linkedItemId).FirstOrDefault(); ArkDroppedItem returnValue = x.AsDroppedItem(linkedItem, save.SaveState); return(returnValue); }).ToArray(); var playerDeathCache = objects.Where(x => x.IsDeathItemCache).Select(x => x.AsDeathCache(save.SaveState)).ToArray(); var structures = objects.Where(x => x.IsStructure).Select(x => x.AsStructure(save.SaveState)).ToArray(); ApplyOrSaveNewData(deferApplyNewData, save, tamed, wild, allplayers, tribes, items, droppedItems, structures, playerDeathCache, anonymize); success = true; } catch (OperationCanceledException) { cancelled = true; } finally { save?.Dispose(); } return(new ArkGameDataUpdateResult { Success = success, Cancelled = cancelled, Elapsed = st.Elapsed }); }