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;
        }
Ejemplo n.º 3
0
        /// <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
            });
        }