Esempio n. 1
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
            });
        }
Esempio n. 2
0
 private void ApplyOrSaveNewData(bool deferApplyNewData, ArkSavegame save, ArkTamedCreature[] tamed, ArkWildCreature[] wild, ArkPlayer[] players, ArkTribe[] tribes, ArkItem[] items, ArkDroppedItem[] droppedItems, ArkStructure[] structures, ArkDeathCache[] deathCache, ArkAnonymizeData anonymize = null)
 {
     if (deferApplyNewData)
     {
         _newData = new dynamic[] { save, tamed, wild, players, tribes, items, droppedItems, structures, deathCache, anonymize };
     }
     else
     {
         ApplyNewData(save, tamed, wild, players, tribes, items, droppedItems, structures, true, deathCache, anonymize);
     }
 }
Esempio n. 3
0
        private void ApplyNewData(ArkSavegame save, ArkTamedCreature[] tamed, ArkWildCreature[] wild, ArkPlayer[] players, ArkTribe[] tribes, ArkItem[] items, ArkDroppedItem[] droppedItems, ArkStructure[] structures, bool decouple = true, ArkDeathCache[] deathCache = null, ArkAnonymizeData anonymize = null)
        {
            // Anonymize data if requested
            if (anonymize != null)
            {
                foreach (var i in players)
                {
                    anonymize.Do(i);
                }
                foreach (var i in tribes)
                {
                    anonymize.Do(i);
                }
                foreach (var i in tamed)
                {
                    anonymize.Do(i);
                }
                foreach (var i in structures)
                {
                    anonymize.Do(i);
                }
            }

            // Setup relations in the domain model between entities
            var newGameData = new ArkGameDataBase(save.SaveState, tamed, wild, players, tribes, items, droppedItems, structures, deathCache);

            newGameData.Initialize(_clusterData);
            foreach (var i in tamed)
            {
                i.Initialize(newGameData, _clusterData);
            }
            foreach (var i in wild)
            {
                i.Initialize(newGameData, _clusterData);
            }
            foreach (var i in players)
            {
                i.Initialize(newGameData, _clusterData);
            }
            foreach (var i in tribes)
            {
                i.Initialize(newGameData, _clusterData);
            }
            foreach (var i in items)
            {
                i.Initialize(newGameData, _clusterData);
            }
            foreach (var i in droppedItems)
            {
                i.Initialize(newGameData, _clusterData);
            }
            foreach (var i in structures)
            {
                i.Initialize(newGameData, _clusterData);
            }
            foreach (var i in deathCache)
            {
                i.Initialize(newGameData, _clusterData);
            }

            if (decouple) //should always be true except for debugging
            {
                // Unset all references to raw extracted game objects and properties to free memory
                foreach (var i in tamed)
                {
                    i.Decouple();
                }
                foreach (var i in wild)
                {
                    i.Decouple();
                }
                foreach (var i in players)
                {
                    i.Decouple();
                }
                foreach (var i in tribes)
                {
                    i.Decouple();
                }
                foreach (var i in items)
                {
                    i.Decouple();
                }
                foreach (var i in droppedItems)
                {
                    i.Decouple();
                }
                foreach (var i in structures)
                {
                    i.Decouple();
                }
                foreach (var i in deathCache)
                {
                    i.Decouple();
                }
            }

            // Assign updated data to public properties
            newGameData.CopyTo(this);

            // Force an immediate garbage collection because it seems more effective (extraction process requires a great deal of memory)
            //GC.Collect();
        }
        public ArkClusterDataUpdateResult Update(CancellationToken ct, bool deferApplyNewData = false, ArkAnonymizeData anonymize = null)
        {
            var success   = false;
            var cancelled = false;
            var st        = Stopwatch.StartNew();

            try
            {
                var exclusivePropertyNameTree = _loadOnlyPropertiesInDomain ? ArkClusterDataContainerBase._alldependencies : null;

                // Extract all cluster data
                var arkcloudInventories = Directory.GetFiles(_savePath, "*", SearchOption.TopDirectoryOnly).Where(x => /*avoid loading duplicate cluster files*/ r_clusterFiles.IsMatch(Path.GetFileName(x))).Select(x => new ArkSavegameToolkitNet.ArkCloudInventory(x, exclusivePropertyNameTree: exclusivePropertyNameTree)).ToArray();

                var cloudInventories = arkcloudInventories.Where(x => x.InventoryData != null).Select(x => x.InventoryData.AsCloudInventory(x.SteamId, SaveState.FromSaveTime(x.SaveTime), x.InventoryDinoData)).ToArray();

                ApplyOrSaveNewData(deferApplyNewData, cloudInventories);

                success = true;
            }
            catch (OperationCanceledException)
            {
                cancelled = true;
            }

            return(new ArkClusterDataUpdateResult {
                Success = success, Cancelled = cancelled, Elapsed = st.Elapsed
            });
        }