private void writeList(KeyValuePair <string, List <GameObject> > entry)
        {
            string outputFile = Path.Combine(outputDirectory, entry.Key + ".json");

            List <GameObject> filteredClasses = entry.Value;
            MapData           mapData         = LatLonCalculator.ForSave(arkSavegame);

            CommonFunctions.WriteJson(outputFile, (generator, writingOptions) => {
                if (statistics)
                {
                    generator.WriteStartObject();

                    generator.WriteField("count", filteredClasses.Count);

                    List <int> summaryStatistics = filteredClasses.Where(o => o.IsWild())
                                                   .Select(a => a.GetBaseLevel(arkSavegame)).ToList();
                    if (summaryStatistics.Any())
                    {
                        generator.WriteField("wildMin", summaryStatistics.Min());
                        generator.WriteField("wildMax", summaryStatistics.Max());
                        generator.WriteField("wildAverage", summaryStatistics.Average());
                    }

                    List <int> tamedBaseStatistics = filteredClasses.Where(o => o.IsTamed())
                                                     .Select(a => a.GetBaseLevel(arkSavegame)).ToList();
                    if (tamedBaseStatistics.Any())
                    {
                        generator.WriteField("tamedBaseMin", tamedBaseStatistics.Min());
                        generator.WriteField("tamedBaseMax", tamedBaseStatistics.Max());
                        generator.WriteField("tamedBaseAverage", tamedBaseStatistics.Average());
                    }

                    List <int> tamedFullStatistics = filteredClasses.Where(o => o.IsTamed())
                                                     .Select(a => a.GetFullLevel(arkSavegame)).ToList();
                    if (tamedFullStatistics.Any())
                    {
                        generator.WriteField("tamedFullMin", tamedFullStatistics.Min());
                        generator.WriteField("tamedFullMax", tamedFullStatistics.Max());
                        generator.WriteField("tamedFullAverage", tamedFullStatistics.Average());
                    }

                    generator.WritePropertyName("dinos");
                    generator.WriteStartArray();
                }
                else
                {
                    generator.WriteStartArray();
                }

                CustomDataContext context = new CustomDataContext {
                    MapData         = mapData,
                    ObjectContainer = container,
                    Savegame        = arkSavegame
                };
                foreach (GameObject creatureObject in filteredClasses)
                {
                    Creature creature = new Creature(creatureObject, container);
                    generator.WriteStartObject();
                    creature.writeAllProperties(generator, context, writeAllFields);
                    if (!string.IsNullOrWhiteSpace(inventory))
                    {
                        creature.writeInventory(generator, context, writeAllFields, inventory == "summary");
                    }

                    generator.WriteEndObject();
                }

                generator.WriteEndArray();

                if (statistics)
                {
                    generator.WriteEndObject();
                }
            }, writingOptions);
        }
Example #2
0
        protected override void RunCommand(IEnumerable <string> args)
        {
            List <string> argsList = args.ToList();

            if (showCommandHelp(argsList))
            {
                return;
            }

            bool itemsLong      = withItems == "long";
            bool inventoryLong  = withInventory == "long";
            bool tamedLong      = tamed == "long";
            bool structuresLong = withStructures == "long";

            Stopwatch stopwatch = new Stopwatch(GlobalOptions.UseStopWatch);

            bool mapNeeded = withItems != null || tamed != null || withStructures != null || withInventory != null;

            if (!GlobalOptions.Quiet && mapNeeded)
            {
                Console.WriteLine("Need to load map, this may take some time...");
            }

            string saveGame        = argsList.Count > 0 ? argsList[0] : Path.Combine(GlobalOptions.ArkToolsConfiguration.BasePath, GlobalOptions.ArkToolsConfiguration.ArkSavegameFilename);
            string outputDirectory = argsList.Count > 1 ? argsList[1] : Path.Combine(GlobalOptions.ArkToolsConfiguration.BasePath, GlobalOptions.ArkToolsConfiguration.TribesPath);
            string saveDir         = Path.GetDirectoryName(saveGame);

            Dictionary <int, HashSet <TribeBase> > baseMap;
            CustomDataContext context = new CustomDataContext();

            if (mapNeeded)
            {
                ArkDataManager.LoadData(GlobalOptions.Language);

                ArkSavegame mapSave = new ArkSavegame().ReadBinary <ArkSavegame>(saveGame, ReadingOptions.Create().WithBuildComponentTree(true));
                context.Savegame = mapSave;
                context.MapData  = LatLonCalculator.ForSave(context.Savegame);
                stopwatch.Stop("Loading map data");
                if (withBases)
                {
                    baseMap = new Dictionary <int, HashSet <TribeBase> >();
                    foreach (GameObject gameObject in mapSave)
                    {
                        // Skip items and stuff without a location
                        if (gameObject.IsItem || gameObject.Location == null)
                        {
                            continue;
                        }

                        string signText      = gameObject.GetPropertyValue <string>("SignText");
                        long?  targetingTeam = gameObject.GetPropertyValue <long?>("TargetingTeam");

                        if (signText != null && targetingTeam != null)
                        {
                            // Might be a 'Base' sign
                            MatchCollection matcher = basePattern.Matches(signText);
                            if (matcher.Any())
                            {
                                // Found a base sign, add it to the set, automatically replacing duplicates
                                int          tribeId  = (int)targetingTeam;
                                LocationData location = gameObject.Location;
                                string       baseName = matcher[1].Value;
                                float        size     = float.Parse(matcher[2].Value);

                                TribeBase tribeBase = new TribeBase(baseName, location.X, location.Y, location.Z, size);

                                if (!baseMap.ContainsKey(tribeId))
                                {
                                    baseMap[tribeId] = new HashSet <TribeBase>();
                                }

                                baseMap[tribeId].Add(tribeBase);
                            }
                        }
                    }

                    stopwatch.Stop("Collecting bases");
                }
                else
                {
                    baseMap = null;
                }

                if (mapSave.HibernationEntries.Any() && tamed != null)
                {
                    List <GameObject> combinedObjects = context.Savegame.Objects.ToList();

                    foreach (HibernationEntry entry in context.Savegame.HibernationEntries)
                    {
                        ObjectCollector collector = new ObjectCollector(entry, 1);
                        combinedObjects.AddRange(collector.Remap(combinedObjects.Count));
                    }

                    context.ObjectContainer = new GameObjectContainer(combinedObjects);
                }
                else
                {
                    context.ObjectContainer = mapSave;
                }
            }
            else
            {
                baseMap = null;
            }

            List <Action> tasks = GlobalOptions.Parallel ? new List <Action>() : null;

            void mapWriter(JsonTextWriter generator, int tribeId)
            {
                if (!mapNeeded)
                {
                    return;
                }
                List <GameObject>  structures   = new List <GameObject>();
                List <GameObject>  creatures    = new List <GameObject>();
                List <Item>        items        = new List <Item>();
                List <Item>        blueprints   = new List <Item>();
                List <DroppedItem> droppedItems = new List <DroppedItem>();
                // Apparently there is a behavior in ARK causing certain structures to exist twice within a save
                HashSet <ArkName> processedList = new HashSet <ArkName>();
                // Bases
                HashSet <TribeBase> bases = withBases ? baseMap[tribeId] : null;

                foreach (GameObject gameObject in context.ObjectContainer)
                {
                    if (gameObject.IsItem)
                    {
                        continue;
                    }

                    int targetingTeam = gameObject.GetPropertyValue <int>("TargetingTeam", defaultValue: -1);
                    if (targetingTeam == -1)
                    {
                        continue;
                    }

                    TeamType teamType = TeamTypes.ForTeam(targetingTeam);
                    if (tribeId == -1 && teamType != TeamType.Player)
                    {
                        continue;
                    }

                    if (tribeId == 0 && teamType != TeamType.NonPlayer)
                    {
                        continue;
                    }

                    if (tribeId > 0 && tribeId != targetingTeam)
                    {
                        continue;
                    }

                    // Determine base if we have bases
                    TribeBase tribeBase;
                    if (bases != null && gameObject.Location != null)
                    {
                        TribeBase matchedBase = null;
                        foreach (TribeBase potentialBase in bases)
                        {
                            if (potentialBase.InsideBounds(gameObject.Location))
                            {
                                matchedBase = potentialBase;
                                break;
                            }
                        }

                        tribeBase = matchedBase;
                    }
                    else
                    {
                        tribeBase = null;
                    }

                    if (gameObject.IsCreature())
                    {
                        if (!processedList.Contains(gameObject.Names[0]))
                        {
                            if (tribeBase != null)
                            {
                                tribeBase.Creatures.Add(gameObject);
                            }
                            else
                            {
                                creatures.Add(gameObject);
                            }

                            processedList.Add(gameObject.Names[0]);
                        }
                        else
                        {
                            // Duped Creature
                            continue;
                        }
                    }
                    else if (!gameObject.IsPlayer() && !gameObject.IsWeapon() && !gameObject.IsDroppedItem())
                    {
                        // LinkedPlayerDataID: Players ain't structures
                        // AssociatedPrimalItem: Items equipped by sleeping players
                        // MyItem: dropped item
                        if (!processedList.Contains(gameObject.Names[0]))
                        {
                            if (tribeBase != null)
                            {
                                tribeBase.Structures.Add(gameObject);
                            }
                            else
                            {
                                structures.Add(gameObject);
                            }

                            processedList.Add(gameObject.Names[0]);
                        }
                        else
                        {
                            // Duped Structure
                            continue;
                        }
                    }
                    else
                    {
                        if (!processedList.Contains(gameObject.Names[0]))
                        {
                            processedList.Add(gameObject.Names[0]);
                        }
                        else
                        {
                            // Duped Player or dropped Item or weapon
                            continue;
                        }
                    }

                    void itemHandler(ObjectReference itemReference)
                    {
                        GameObject item = itemReference.GetObject(context.Savegame);

                        if (item != null && !Item.isDefaultItem(item))
                        {
                            if (processedList.Contains(item.Names[0]))
                            {
                                // happens for players having items in their quick bar
                                return;
                            }

                            processedList.Add(item.Names[0]);

                            if (item.HasAnyProperty("bIsBlueprint"))
                            {
                                if (tribeBase != null)
                                {
                                    tribeBase.Blueprints.Add(new Item(item));
                                }
                                else
                                {
                                    blueprints.Add(new Item(item));
                                }
                            }
                            else
                            {
                                if (tribeBase != null)
                                {
                                    tribeBase.Items.Add(new Item(item));
                                }
                                else
                                {
                                    items.Add(new Item(item));
                                }
                            }
                        }
                    }

                    void droppedItemHandler(GameObject droppedItemObject)
                    {
                        DroppedItem droppedItem = new DroppedItem(droppedItemObject, context.Savegame);

                        if (tribeBase != null)
                        {
                            tribeBase.DroppedItems.Add(droppedItem);
                        }
                        else
                        {
                            droppedItems.Add(droppedItem);
                        }
                    }

                    if (withItems != null && withInventory == null)
                    {
                        foreach (GameObject inventory in gameObject.Components.Values)
                        {
                            if (!inventory.IsInventory())
                            {
                                continue;
                            }

                            List <ObjectReference> inventoryItems = inventory.GetPropertyValue <IArkArray, ArkArrayObjectReference>("InventoryItems");
                            foreach (ObjectReference itemReference in inventoryItems ?? Enumerable.Empty <ObjectReference>())
                            {
                                itemHandler(itemReference);
                            }

                            List <ObjectReference> equippedItems = inventory.GetPropertyValue <IArkArray, ArkArrayObjectReference>("EquippedItems");
                            foreach (ObjectReference itemReference in equippedItems ?? Enumerable.Empty <ObjectReference>())
                            {
                                itemHandler(itemReference);
                            }
                        }
                    }

                    ObjectReference myItem = gameObject.GetPropertyValue <ObjectReference>("MyItem");

                    if (myItem != null)
                    {
                        if (withItems != null && withInventory == null)
                        {
                            itemHandler(myItem);
                        }
                        else if (withInventory != null)
                        {
                            droppedItemHandler(gameObject);
                        }
                    }
                }

                void writeStructures(IEnumerable <GameObject> structList)
                {
                    if (withStructures == null)
                    {
                        return;
                    }
                    generator.WriteArrayFieldStart("structures");

                    if (structuresLong)
                    {
                        foreach (GameObject structureObject in structList)
                        {
                            Structure structure = new Structure(structureObject, context.Savegame);

                            generator.WriteStartObject();

                            structure.writeAllProperties(generator, context, writeAllFields);

                            if (withInventory != null)
                            {
                                structure.writeInventory(generator, context, writeAllFields, !inventoryLong);
                            }

                            generator.WriteEndObject();
                        }
                    }
                    else
                    {
                        Dictionary <ArkName, long> structMap = structList.GroupBy(o => o.ClassName).ToDictionary(objects => objects.Key, objects => objects.LongCount());
                        foreach (KeyValuePair <ArkName, long> entry in structMap.OrderByDescending(pair => pair.Value))
                        {
                            generator.WriteStartObject();

                            string name = entry.Key.ToString();
                            if (ArkDataManager.HasStructure(name))
                            {
                                name = ArkDataManager.GetStructure(name).Name;
                            }

                            generator.WriteField("name", name);
                            generator.WriteField("count", entry.Value);

                            generator.WriteEndObject();
                        }
                    }

                    generator.WriteEndArray();
                }

                void writeCreatures(List <GameObject> creaList)
                {
                    if (tamed == null)
                    {
                        return;
                    }
                    generator.WriteArrayFieldStart("tamed");

                    if (tamedLong)
                    {
                        foreach (GameObject creatureObject in creaList)
                        {
                            Creature creature = new Creature(creatureObject, context.Savegame);

                            generator.WriteStartObject();

                            creature.writeAllProperties(generator, context, writeAllFields);

                            if (withInventory != null)
                            {
                                creature.writeInventory(generator, context, writeAllFields, !inventoryLong);
                            }

                            generator.WriteEndObject();
                        }
                    }
                    else
                    {
                        Dictionary <ArkName, long> creaMap = creaList.GroupBy(o => o.ClassName).ToDictionary(objects => objects.Key, objects => objects.LongCount());
                        foreach (KeyValuePair <ArkName, long> entry in creaMap.OrderByDescending(pair => pair.Value))
                        {
                            generator.WriteStartObject();

                            string name = entry.Key.ToString();
                            if (ArkDataManager.HasCreature(name))
                            {
                                name = ArkDataManager.GetCreature(name).Name;
                            }

                            generator.WriteField("name", name);
                            generator.WriteField("count", entry.Value);

                            generator.WriteEndObject();
                        }
                    }

                    generator.WriteEndArray();
                }

                void writeDroppedItems(List <DroppedItem> droppedList)
                {
                    if (withInventory == null)
                    {
                        return;
                    }
                    generator.WriteArrayFieldStart("droppedItems");

                    foreach (DroppedItem droppedItem in droppedList)
                    {
                        generator.WriteStartObject();

                        droppedItem.writeAllProperties(generator, context, writeAllFields);
                        droppedItem.writeInventory(generator, context, writeAllFields, !inventoryLong);

                        generator.WriteEndObject();
                    }

                    generator.WriteEndArray();
                }

                if (withBases && bases != null)
                {
                    generator.WriteArrayFieldStart("bases");

                    foreach (TribeBase tribeBase in bases)
                    {
                        generator.WriteStartObject();

                        generator.WriteField("name", tribeBase.Name);
                        generator.WriteField("x", tribeBase.X);
                        generator.WriteField("y", tribeBase.Y);
                        generator.WriteField("z", tribeBase.Z);
                        generator.WriteField("lat", context.MapData.CalculateLat(tribeBase.Y));
                        generator.WriteField("lon", context.MapData.CalculateLon(tribeBase.X));
                        generator.WriteField("radius", tribeBase.Size);
                        writeCreatures(tribeBase.Creatures);
                        writeStructures(tribeBase.Structures);
                        writeDroppedItems(tribeBase.DroppedItems);
                        if (itemsLong)
                        {
                            generator.WritePropertyName("items");
                            Inventory.writeInventoryLong(generator, context, tribeBase.Items, writeAllFields);
                            generator.WritePropertyName("blueprints");
                            Inventory.writeInventoryLong(generator, context, tribeBase.Blueprints, writeAllFields);
                        }
                        else
                        {
                            generator.WritePropertyName("items");
                            Inventory.writeInventorySummary(generator, tribeBase.Items);
                            generator.WritePropertyName("blueprints");
                            Inventory.writeInventorySummary(generator, tribeBase.Blueprints);
                        }

                        generator.WriteEndObject();
                    }

                    generator.WriteStartObject();
                }

                writeCreatures(creatures);
                writeStructures(structures);
                writeDroppedItems(droppedItems);
                if (itemsLong)
                {
                    generator.WritePropertyName("items");
                    Inventory.writeInventoryLong(generator, context, items, writeAllFields);
                    generator.WritePropertyName("blueprints");
                    Inventory.writeInventoryLong(generator, context, blueprints, writeAllFields);
                }
                else
                {
                    generator.WritePropertyName("items");
                    Inventory.writeInventorySummary(generator, items);
                    generator.WritePropertyName("blueprints");
                    Inventory.writeInventorySummary(generator, blueprints);
                }

                if (withBases && bases != null)
                {
                    generator.WriteEndObject();

                    generator.WriteEndArray();
                }
            }

            foreach (string path in Directory.EnumerateFiles(saveDir).Where(path => tribePattern.IsMatch(path)))
            {
                Action task = () => {
                    try {
                        Tribe tribe = new Tribe(path, ReadingOptions.Create());

                        string tribeFileName = tribe.tribeId + ".json";

                        string tribePath = Path.Combine(outputDirectory, tribeFileName);

                        CommonFunctions.WriteJson(tribePath, (generator, writingOptions) => {
                            generator.WriteStartObject();

                            tribe.writeAllProperties(generator, context, writeAllFields);

                            mapWriter(generator, tribe.tribeId);

                            generator.WriteEndObject();
                        }, writingOptions);
                    } catch (Exception ex) {
                        Console.Error.WriteLine("Found potentially corrupt ArkTribe: " + path);
                        if (GlobalOptions.Verbose)
                        {
                            Console.Error.WriteLine(ex.Message);
                            Console.Error.WriteLine(ex.StackTrace);
                        }
                    }
                };

                if (tasks != null)
                {
                    tasks.Add(task);
                }
                else
                {
                    task();
                }
            }

            if (tasks != null)
            {
                Parallel.ForEach(tasks, task => task());
            }

            if (tribeless)
            {
                string tribePath = Path.Combine(outputDirectory, "tribeless.json");

                CommonFunctions.WriteJson(tribePath, (generator, writingOptions) => {
                    generator.WriteStartObject();

                    mapWriter(generator, -1);

                    generator.WriteEndObject();
                }, writingOptions);
            }

            if (nonPlayers)
            {
                string tribePath = Path.Combine(outputDirectory, "non-players.json");

                CommonFunctions.WriteJson(tribePath, (generator, writingOptions) => {
                    generator.WriteStartObject();

                    mapWriter(generator, 0);

                    generator.WriteEndObject();
                }, writingOptions);
            }

            stopwatch.Stop("Loading tribes and writing info");
            stopwatch.Print();
        }
Example #3
0
        protected override void RunCommand(IEnumerable <string> args)
        {
            List <string> argsList = args.ToList();

            if (showCommandHelp(argsList))
            {
                return;
            }

            ArkDataManager.LoadData(GlobalOptions.Language);

            Stopwatch stopwatch = new Stopwatch(GlobalOptions.UseStopWatch);

            bool mapNeeded = !string.IsNullOrEmpty(inventory) || positions;

            if (!GlobalOptions.Quiet && mapNeeded)
            {
                Console.WriteLine("Need to load map, this may take some time...");
            }

            string saveGame = argsList.Count > 0
                    ? argsList[0]
                    : Path.Combine(GlobalOptions.ArkToolsConfiguration.BasePath, GlobalOptions.ArkToolsConfiguration.ArkSavegameFilename);
            string outputDirectory = argsList.Count > 1 ? argsList[1] : Path.Combine(GlobalOptions.ArkToolsConfiguration.BasePath, GlobalOptions.ArkToolsConfiguration.PlayersPath);
            string saveDir         = Path.GetDirectoryName(saveGame);

            CustomDataContext context = new CustomDataContext();

            if (mapNeeded)
            {
                ArkSavegame mapSave = new ArkSavegame().ReadBinary <ArkSavegame>(saveGame, ReadingOptions.Create().WithBuildComponentTree(true));
                context.ObjectContainer = mapSave;
                context.Savegame        = mapSave;
                context.MapData         = LatLonCalculator.ForSave(mapSave);
                stopwatch.Stop("Loading map data");
            }

            Dictionary <int, Tribe> tribes = new Dictionary <int, Tribe>();
            List <Action>           tasks  = GlobalOptions.Parallel ? new List <Action>() : null;

            foreach (string path in Directory.EnumerateFiles(saveDir).Where(path => profilePattern.IsMatch(Path.GetFileName(path))))
            {
                if (maxAge.HasValue)
                {
                    DateTimeOffset fileTime = File.GetLastWriteTimeUtc(path);

                    if (fileTime < DateTimeOffset.UtcNow.AddSeconds(-maxAge.Value))
                    {
                        continue;
                    }
                }

                Action task = () => {
                    try {
                        Player player = new Player(path, context, ReadingOptions.Create());

                        long playerId = player.playerDataId;

                        string playerFileName;
                        if (naming == "steamid" || string.IsNullOrWhiteSpace(naming))
                        {
                            playerFileName = player.uniqueId.NetId + ".json";
                        }
                        else if (naming == "playerid")
                        {
                            playerFileName = playerId + ".json";
                        }
                        else
                        {
                            throw new Exception("Invalid value for parameter naming.");
                        }

                        if (player.tribeId != 0)
                        {
                            if (!tribes.ContainsKey(player.tribeId))
                            {
                                string tribePath = Path.Combine(saveDir, player.tribeId + ".arktribe");
                                if (File.Exists(tribePath))
                                {
                                    try {
                                        tribes[player.tribeId] = new Tribe(tribePath, ReadingOptions.Create());
                                    } catch (Exception ex) {
                                        // Either the header didn't match or one of the properties is missing
                                        Console.Error.WriteLine("Found potentially corrupt ArkTribe: " + tribePath);
                                        if (GlobalOptions.Verbose)
                                        {
                                            Console.Error.WriteLine(ex.Message);
                                            Console.Error.WriteLine(ex.StackTrace);
                                        }
                                    }
                                }
                            }
                        }

                        string playerPath = Path.Combine(outputDirectory, playerFileName);

                        void writePlayer(JsonTextWriter writer, WritingOptions options)
                        {
                            writer.WriteStartObject();

                            // Player data

                            player.WriteAllProperties(writer, context, writeAllFields, noPrivacy);

                            // Inventory
                            if (!string.IsNullOrEmpty(inventory))
                            {
                                player.WriteInventory(writer, context, writeAllFields, inventory.ToLowerInvariant() != "long");
                            }

                            // Tribe

                            if (player.tribeId != 0 && tribes.TryGetValue(player.tribeId, out Tribe tribe))
                            {
                                writer.WriteField("tribeName", tribe.tribeName);

                                if (writeAllFields || tribe.ownerPlayerDataId == playerId)
                                {
                                    writer.WriteField("tribeOwner", tribe.ownerPlayerDataId == playerId);
                                }

                                if (writeAllFields || tribe.tribeAdmins.Contains((int)playerId))
                                {
                                    writer.WriteField("tribeAdmin", tribe.tribeAdmins.Contains((int)playerId));
                                }
                            }

                            writer.WriteEndObject();
                        }

                        CommonFunctions.WriteJson(playerPath, writePlayer, writingOptions);
                    } catch (Exception ex) when(!Debugger.IsAttached)
                    {
                        Console.Error.WriteLine("Found potentially corrupt ArkProfile: " + path);
                        if (GlobalOptions.Verbose)
                        {
                            Console.Error.WriteLine(ex.Message);
                            Console.Error.WriteLine(ex.StackTrace);
                        }
                    }
                };

                if (tasks != null)
                {
                    tasks.Add(task);
                }
                else
                {
                    task();
                }
            }

            if (tasks != null)
            {
                Parallel.ForEach(tasks, task => task());
            }

            stopwatch.Stop("Loading profiles and writing info");
            stopwatch.Print();
        }
Example #4
0
        public void LoadSavegame(string path)
        {
            Savegame = new ArkSavegame().ReadBinary <ArkSavegame>(path, ReadingOptions.Create()
                                                                  // Skip things like NPCZoneVolume and non-instanced objects
                                                                  .WithObjectFilter(obj => !obj.FromDataFile && (obj.Names.Count > 1 || obj.Names[0].Instance > 0))
                                                                  .WithBuildComponentTree(true));
            MapData = LatLonCalculator.ForSave(Savegame);

            if (Savegame.HibernationEntries.Any())
            {
                List <GameObject> combinedObjects = new List <GameObject>(Savegame.Objects);

                foreach (HibernationEntry entry in Savegame.HibernationEntries)
                {
                    ObjectCollector collector = new ObjectCollector(entry, 1);
                    combinedObjects.AddRange(collector.Remap(combinedObjects.Count));
                }

                ObjectContainer = new GameObjectContainer(combinedObjects);
            }
            else
            {
                ObjectContainer = Savegame;
            }

            foreach (GameObject gameObject in ObjectContainer)
            {
                if (gameObject.FromDataFile || (gameObject.Names.Count == 1 && gameObject.Names[0].Instance == 0))
                {
                    // Skip things like NPCZoneVolume and non-instanced objects
                }
                else if (gameObject.IsInventory())
                {
                    InventoryMap[gameObject.Id] = new Inventory(gameObject);
                }
                else
                {
                    if (!nameObjectMap.ContainsKey(gameObject.Names[0]))
                    {
                        nameObjectMap[gameObject.Names[0]] = gameObject.Id;
                        if (gameObject.IsItem)
                        {
                            ItemMap[gameObject.Id] = new Item(gameObject);
                        }
                        else if (gameObject.IsCreature())
                        {
                            CreatureMap[gameObject.Id] = new Creature(gameObject, Savegame);
                        }
                        else if (gameObject.Location != null &&
                                 !gameObject.IsPlayer() &&
                                 !gameObject.IsDroppedItem() &&
                                 !gameObject.IsWeapon())
                        {
                            // Skip players, weapons and items on the ground
                            // is (probably) a structure
                            StructureMap[gameObject.Id] = new Structure(gameObject, Savegame);
                        }
                        else if (gameObject.IsDroppedItem())
                        {
                            // dropped Item
                            DroppedItemMap[gameObject.Id] = new DroppedItem(gameObject, Savegame);
                        }
                    }
                }
            }
        }