Пример #1
0
        public void Write()
        {
            // Set City Folk Bed first
            if (_saveData.SaveGeneration == SaveGeneration.Wii && House != null && Data.Bed != null)
            {
                House.Data.Bed = Data.Bed;
                Data.Bed       = null;
            }

            var playerSaveInfoType = typeof(PlayerSaveInfo);
            var playerDataType     = typeof(PlayerData);

            foreach (var field in playerSaveInfoType.GetFields(BindingFlags.Public | BindingFlags.Instance))
            {
                if (field.GetValue(Offsets) == null || field.Name.Contains("Count") ||
                    field.Name.Contains("Size"))
                {
                    continue;
                }
                if (playerDataType.GetField(field.Name) == null)
                {
                    continue;
                }
                if (field.FieldType != typeof(int) || (int)field.GetValue(Offsets) == -1)
                {
                    continue;
                }

                var fieldType  = typeof(PlayerData).GetField(field.Name).FieldType;
                var dataOffset = Offset + (int)field.GetValue(Offsets);
                switch (field.Name)
                {
                case "TownPassCardImage" when _saveData.SaveGeneration == SaveGeneration.N3DS:
                    _saveData.Write(dataOffset, Data.TownPassCardData);
                    break;

                case "Reset" when _saveData.SaveGeneration == SaveGeneration.GCN:
                    _saveData.Write(dataOffset, Data.Reset ? (uint)0x250C : (uint)0, _saveData.IsBigEndian);
                    break;

                default:
                    if (fieldType == typeof(string))
                    {
                        _saveData.Write(dataOffset, AcString.GetBytes((string)playerDataType.GetField(field.Name).GetValue(Data),
                                                                      (int)playerSaveInfoType.GetField(field.Name + "Size").GetValue(Offsets)));
                    }
                    else if (fieldType == typeof(byte))
                    {
                        if (_saveData.SaveType == SaveType.WildWorld)
                        {
                            switch (field.Name)
                            {
                            case "HairColor":
                            {
                                var condensedData = (byte)(Data.HairColor & 0x0F);       //Remove upper nibble just incase
                                condensedData += (byte)((Data.Tan & 0x0F) << 4);         //Add in tan to the byte
                                _saveData.Write(dataOffset, condensedData);
                                break;
                            }

                            case "HairType":
                            {
                                var condensedData = (byte)(Data.FaceType & 0x0F);
                                condensedData += (byte)((Data.HairType & 0x0F) << 4);
                                _saveData.Write(dataOffset, condensedData);
                                break;
                            }

                            default:
                                _saveData.Write(dataOffset, (byte)playerDataType.GetField(field.Name).GetValue(Data));
                                break;
                            }
                        }
                        else if (_saveData.SaveType == SaveType.CityFolk)
                        {
                            switch (field.Name)
                            {
                            case "Tan":
                                var shiftedData = (byte)(Data.Tan << 1);         //ACToolkit does this
                                _saveData.Write(dataOffset, shiftedData);
                                break;

                            case "FaceType":
                                _saveData.Write(dataOffset, (byte)(Data.EyeColor + Data.FaceType));
                                break;

                            default:
                                _saveData.Write(dataOffset, (byte)playerDataType.GetField(field.Name).GetValue(Data));
                                break;
                            }
                        }
                        else
                        {
                            _saveData.Write(dataOffset, (byte)playerDataType.GetField(field.Name).GetValue(Data));
                        }
                    }
                    else if (fieldType == typeof(ushort))
                    {
                        _saveData.Write(dataOffset, (ushort)playerDataType.GetField(field.Name).GetValue(Data), _saveData.IsBigEndian);
                    }
                    else if (fieldType == typeof(uint))
                    {
                        _saveData.Write(dataOffset, (uint)playerDataType.GetField(field.Name).GetValue(Data), _saveData.IsBigEndian);
                    }
                    else if (fieldType == typeof(Inventory))
                    {
                        if (_saveData.SaveGeneration == SaveGeneration.N3DS)
                        {
                            var items = new uint[Offsets.PocketsCount];
                            for (var i = 0; i < items.Length; i++)
                            {
                                items[i] = ItemData.EncodeItem(Data.Pockets.Items[i]);
                            }
                            _saveData.Write(dataOffset, items);
                        }
                        else
                        {
                            var items = new ushort[Offsets.PocketsCount];
                            for (var i = 0; i < items.Length; i++)
                            {
                                items[i] = Data.Pockets.Items[i].ItemId;
                            }
                            _saveData.Write(dataOffset, items, _saveData.IsBigEndian);
                        }
                    }
                    else if (fieldType == typeof(Item))
                    {
                        var item = (Item)playerDataType.GetField(field.Name).GetValue(Data);
                        if (_saveData.SaveGeneration == SaveGeneration.N3DS)
                        {
                            _saveData.Write(dataOffset, item.ToUInt32());
                        }
                        else
                        {
                            if (field.Name.Equals("Shirt") &&
                                (_saveData.SaveGeneration == SaveGeneration.N64 || _saveData.SaveGeneration == SaveGeneration.GCN ||
                                 _saveData.SaveGeneration == SaveGeneration.iQue))     // For some reason, the shirt lower byte is also stored before the actual item id.
                            {
                                _saveData.Write(dataOffset - 1, new[] { (byte)item.ItemId, (byte)(item.ItemId >> 8), (byte)item.ItemId }, _saveData.IsBigEndian);
                            }
                            else
                            {
                                _saveData.Write(dataOffset, item.ItemId, _saveData.IsBigEndian);
                            }
                        }
                    }
                    else if (fieldType == typeof(Item[]))
                    {
                        var itemArray = (Item[])playerDataType.GetField(field.Name).GetValue(Data);
                        if (field.Name.Equals("Dressers"))
                        {
                            switch (_saveData.SaveGeneration)
                            {
                            case SaveGeneration.NDS:
                                dataOffset = _saveData.SaveDataStartOffset + 0x15430 + 0xB4 * Index;         // Terrible hack
                                break;

                            case SaveGeneration.Wii:
                                dataOffset = _saveData.SaveDataStartOffset + 0x1F3038 + 0x140 * Index;
                                break;
                            }
                        }

                        for (var i = 0; i < itemArray.Length; i++)
                        {
                            if (_saveData.SaveGeneration == SaveGeneration.N3DS)
                            {
                                _saveData.Write(dataOffset + i * 4, itemArray[i].ToUInt32());
                            }
                            else
                            {
                                _saveData.Write(dataOffset + i * 2, itemArray[i].ItemId, _saveData.IsBigEndian);
                            }
                        }
                    }
                    else if (fieldType == typeof(NewLeafInt32))
                    {
                        if (_saveData.SaveGeneration == SaveGeneration.NDS)
                        {
                            var encryptedInt = (NewLeafInt32)playerDataType.GetField(field.Name).GetValue(Data);
                            _saveData.Write(dataOffset, encryptedInt.Int1);
                            _saveData.Write(dataOffset + 4, encryptedInt.Int2);
                        }
                    }
                    else if (fieldType == typeof(AcDate) && (_saveData.SaveGeneration == SaveGeneration.GCN ||
                                                             _saveData.SaveGeneration == SaveGeneration.NDS ||
                                                             _saveData.SaveGeneration == SaveGeneration.Wii))
                    {
                        if (field.Name.Equals("Birthday"))
                        {
                            _saveData.Write(dataOffset, ((AcDate)playerDataType.GetField(field.Name).GetValue(Data)).ToMonthDayDateData());
                        }
                    }

                    break;
                }
            }
        }
Пример #2
0
        public virtual void Write()
        {
            var saveData = Save.SaveInstance;
            var offsets  = HouseInfo.GetHouseOffsets(saveData.SaveType);

            // Set House TownID & Name
            if (Owner != null)
            {
                if (offsets.OwningPlayerName != -1 && offsets.TownId != -1)
                {
                    Data.TownId =
                        saveData.ReadUInt16(saveData.SaveDataStartOffset + Save.SaveInstance.SaveInfo.SaveOffsets.TownId,
                                            saveData.IsBigEndian); // Might not be UInt16 in all games
                }

                if (offsets.OwningPlayerName != -1 && offsets.TownName != -1)
                {
                    Data.TownName = saveData.ReadString(
                        saveData.SaveDataStartOffset + Save.SaveInstance.SaveInfo.SaveOffsets.TownName,
                        Save.SaveInstance.SaveInfo.SaveOffsets.TownNameSize);
                }

                if (offsets.OwningPlayerName != -1)
                {
                    Data.OwningPlayerName = Owner.Data.Name;
                }

                if (offsets.OwningPlayerId != -1)
                {
                    Data.OwningPlayerId = Owner.Data.Identifier;
                }
            }

            var houseOffsetData = typeof(HouseOffsets);
            var houseDataType   = typeof(HouseData);

            foreach (var field in houseOffsetData.GetFields(BindingFlags.Public | BindingFlags.Instance))
            {
                if (field.GetValue(offsets) == null || field.Name.Contains("Count") ||
                    field.Name.Contains("Size"))
                {
                    continue;
                }
                if (houseDataType.GetField(field.Name) == null)
                {
                    continue;
                }
                if (field.FieldType != typeof(int) || (int)field.GetValue(offsets) == -1)
                {
                    continue;
                }
                var fieldType  = houseDataType.GetField(field.Name).FieldType;
                var dataOffset = Offset + (int)field.GetValue(offsets);
                //MessageBox.Show("Field Name: " + Field.Name + " | Data Offset: " + DataOffset.ToString("X"));
                if (fieldType == typeof(string))
                {
                    saveData.Write(dataOffset, AcString.GetBytes((string)houseDataType.GetField(field.Name).GetValue(Data),
                                                                 (int)houseOffsetData.GetField(field.Name + "Size").GetValue(offsets)));
                }
                else if (fieldType == typeof(byte))
                {
                    saveData.Write(dataOffset, (byte)houseDataType.GetField(field.Name).GetValue(Data));
                }
                else if (fieldType == typeof(byte[]))
                {
                    saveData.Write(dataOffset, (byte[])houseDataType.GetField(field.Name).GetValue(Data));
                }
                else if (fieldType == typeof(ushort))
                {
                    saveData.Write(dataOffset, (ushort)houseDataType.GetField(field.Name).GetValue(Data), saveData.IsBigEndian);
                }
                else if (fieldType == typeof(Item))
                {
                    if (saveData.SaveGeneration == SaveGeneration.N3DS)
                    {
                        saveData.Write(dataOffset, ItemData.EncodeItem((Item)houseDataType.GetField(field.Name).GetValue(Data)), saveData.IsBigEndian);
                    }
                    else
                    {
                        saveData.Write(dataOffset, ((Item)houseDataType.GetField(field.Name).GetValue(Data)).ItemId, saveData.IsBigEndian);
                    }
                }
            }

            foreach (var r in Data.Rooms)
            {
                r.Write();
            }
        }
Пример #3
0
        public void Write(string townName)
        {
            // Set Villager TownID & Name when villager exists.
            if (Exists && _saveData.SaveGeneration != SaveGeneration.iQue) // TODO: Once iQue text is implemented, remove this.
            {
                if (Offsets.TownId != -1)
                {
                    Data.TownId =
                        _saveData.ReadUInt16(
                            _saveData.SaveDataStartOffset + Save.SaveInstance.SaveInfo.SaveOffsets.TownId,
                            _saveData.IsBigEndian); // Might not be UInt16 in all games
                }
                if (!string.IsNullOrWhiteSpace(townName) && Offsets.TownName != -1)
                {
                    Data.TownName = townName;
                }
            }

            if (!Exists)
            {
                return;          // TODO: Do I need this? it overwrites important stuff in Animal Forest iQue if I don't have it.
            }
            var villagerOffsetData = typeof(VillagerOffsets);
            var villagerDataType   = typeof(VillagerDataStruct);

            foreach (var field in villagerOffsetData.GetFields(BindingFlags.Public | BindingFlags.Instance))
            {
                if (field.GetValue(Offsets) == null || field.Name.Contains("Count") ||
                    field.Name.Contains("Size"))
                {
                    continue;
                }
                if (villagerDataType.GetField(field.Name) == null)
                {
                    continue;
                }
                if (field.FieldType != typeof(int) || (int)field.GetValue(Offsets) == -1)
                {
                    continue;
                }

                var     fieldType  = villagerDataType.GetField(field.Name).FieldType;
                var     dataOffset = Offset + (int)field.GetValue(Offsets);
                dynamic dataObject = villagerDataType.GetField(field.Name).GetValue(Data);

                switch (field.Name)
                {
                case "VillagerId" when _saveData.SaveType == SaveType.WildWorld:
                    _saveData.Write(dataOffset, Convert.ToByte(dataObject));
                    break;

                //Might not encompass City Folk
                case "VillagerId":
                    _saveData.Write(dataOffset, dataObject, _saveData.IsBigEndian);
                    break;

                default:
                    if (fieldType == typeof(string))
                    {
                        _saveData.Write(dataOffset,
                                        AcString.GetBytes(dataObject,
                                                          (int)villagerOffsetData.GetField(field.Name + "Size").GetValue(Offsets)));
                    }
                    else if (fieldType == typeof(byte))
                    {
                        _saveData.Write(dataOffset, (byte)dataObject);
                    }
                    else if (fieldType == typeof(ushort))
                    {
                        _saveData.Write(dataOffset, (ushort)dataObject, _saveData.IsBigEndian);
                    }
                    else if (fieldType == typeof(uint))
                    {
                        _saveData.Write(dataOffset, (uint)dataObject, _saveData.IsBigEndian);
                    }
                    else if (fieldType == typeof(byte[]))
                    {
                        _saveData.Write(dataOffset, dataObject, false);
                    }
                    else if (fieldType == typeof(Item))
                    {
                        switch (_saveData.SaveGeneration)
                        {
                        case SaveGeneration.N3DS:
                            _saveData.Write(dataOffset, ItemData.EncodeItem((Item)dataObject));
                            break;

                        default:
                            _saveData.Write(dataOffset, ((Item)dataObject).ItemId, _saveData.IsBigEndian);
                            break;
                        }
                    }
                    else if (fieldType == typeof(Item[]))
                    {
                        if (dataObject is Item[] collection)
                        {
                            for (var i = 0; i < collection.Length; i++)
                            {
                                switch (_saveData.SaveGeneration)
                                {
                                case SaveGeneration.N3DS:
                                    _saveData.Write(dataOffset + i * 4, ItemData.EncodeItem(collection[i]));
                                    break;

                                default:
                                    _saveData.Write(dataOffset + i * 2, collection[i].ItemId,
                                                    _saveData.IsBigEndian);
                                    break;
                                }
                            }
                        }
                    }
                    else if (!fieldType.IsClass)     // Don't write classes. If we're here, the that means that we haven't handled saving the class.
                    {
                        _saveData.Write(dataOffset, dataObject, _saveData.IsBigEndian);
                    }

                    break;
                }
            }

            // Write AnimalMemories
            if (Exists && AnimalMemories != null)
            {
                foreach (var relation in AnimalMemories)
                {
                    if (relation.Exists)
                    {
                        relation.Write();
                    }
                }
            }

            // Write the NameId for N64/GC/iQue games, & name for e+. TODO: Check if Wild World also has this.
            if (_saveData.SaveGeneration != SaveGeneration.N64 && _saveData.SaveGeneration != SaveGeneration.GCN &&
                _saveData.SaveGeneration != SaveGeneration.iQue)
            {
                return;
            }

            switch (_saveData.SaveType)
            {
            case SaveType.DoubutsuNoMoriPlus:
            case SaveType.AnimalCrossing:
                _saveData.Write(Offset + Offsets.NameId, Index == 15 ? (byte)0xFF : (byte)Data.VillagerId);
                break;

            case SaveType.DoubutsuNoMoriEPlus:     // e+ doesn't set this byte, as they changed the SetNameID function
                _saveData.Write(Offset + 0xC, AcString.GetBytes(Name, 6), false);
                break;

            case SaveType.AnimalForestEPlus:
                _saveData.Write(Offset + 0xC, AcString.GetBytes(Name, 8), false);
                break;

            default:
                _saveData.Write(Offset + Offsets.NameId, (byte)Data.VillagerId);
                break;
            }
        }