예제 #1
0
        /// <summary>Deletes a modfile and binary from the cache.</summary>
        public static bool DeleteModfileAndBinaryZip(int modId, int modfileId)
        {
            string modfilePath = CacheClient.GenerateModfileFilePath(modId, modfileId);
            string zipPath     = CacheClient.GenerateModBinaryZipFilePath(modId, modfileId);

            bool success = true;

            if (!LocalDataStorage.DeleteFile(modfilePath))
            {
                success = false;
            }
            if (!LocalDataStorage.DeleteFile(zipPath))
            {
                success = false;
            }

            return(success);
        }
예제 #2
0
        public static void GetAuthenticatedUserMods(Action <List <ModProfile> > onSuccess,
                                                    Action <WebRequestError> onError)
        {
            List <int> cachedModIds = CacheClient.LoadAuthenticatedUserMods();

            if (cachedModIds != null)
            {
                ModManager.GetModProfiles(cachedModIds,
                                          onSuccess,
                                          onError);
            }
            else
            {
                RequestFilter userModsFilter = new RequestFilter();
                userModsFilter.fieldFilters[GetUserModFilterFields.gameId]
                    = new EqualToFilter <int>()
                    {
                    filterValue = APIClient.gameId
                    };

                Action <List <ModProfile> > onGetMods = (modProfiles) =>
                {
                    CacheClient.SaveModProfiles(modProfiles);

                    List <int> modIds = new List <int>(modProfiles.Count);
                    foreach (ModProfile profile in modProfiles)
                    {
                        modIds.Add(profile.id);
                    }
                    CacheClient.SaveAuthenticatedUserMods(modIds);

                    if (onSuccess != null)
                    {
                        onSuccess(modProfiles);
                    }
                };

                // - Get All Events -
                ModManager.FetchAllResultsForQuery <ModProfile>((p, s, e) => APIClient.GetUserMods(userModsFilter, p, s, e),
                                                                onGetMods,
                                                                onError);
            }
        }
예제 #3
0
        // ------[ INITIALIZATION ]------
        public void OnEnable(SerializedProperty serializedEditableModProfile, ModProfile baseProfile, UserProfile user)
        {
            this.profile           = baseProfile;
            this.youtubeURLsProp   = serializedEditableModProfile.FindPropertyRelative("youtubeURLs");
            this.sketchfabURLsProp = serializedEditableModProfile.FindPropertyRelative("sketchfabURLs");
            this.galleryImagesProp = serializedEditableModProfile.FindPropertyRelative("galleryImageLocators");

            this.isYouTubeExpanded   = false;
            this.isSketchFabExpanded = false;
            this.isImagesExpanded    = false;

            // Initialize textureCache
            this.textureCache = new Dictionary <string, Texture2D>(galleryImagesProp.FindPropertyRelative("value").arraySize);
            for (int i = 0;
                 i < galleryImagesProp.FindPropertyRelative("value").arraySize;
                 ++i)
            {
                string imageFileName = GetGalleryImageFileName(i);
                string imageURL      = GetGalleryImageSource(i);

                if (!String.IsNullOrEmpty(imageFileName) &&
                    !String.IsNullOrEmpty(imageURL))
                {
                    this.textureCache[imageFileName] = ApplicationImages.LoadingPlaceholder;

                    Texture2D texture = CacheClient.ReadImageFile(imageURL);

                    if (texture != null)
                    {
                        this.textureCache[imageFileName] = texture;
                    }
                    else
                    {
                        ModManager.GetModGalleryImage(baseProfile,
                                                      imageFileName,
                                                      IMAGE_PREVIEW_SIZE,
                                                      (t) => { this.textureCache[imageFileName] = t; isRepaintRequired = true; },
                                                      WebRequestError.LogAsWarning);
                    }
                }
            }
        }
 // ------[ UPDATE ]------
 public void OnUpdate()
 {
     if (File.Exists(logoLocation))
     {
         try
         {
             FileInfo imageInfo = new FileInfo(logoLocation);
             if (lastLogoWriteTime < imageInfo.LastWriteTime)
             {
                 logoTexture       = CacheClient.ReadImageFile(logoLocation);
                 lastLogoWriteTime = imageInfo.LastWriteTime;
             }
         }
         catch (Exception e)
         {
             Debug.LogWarning("[mod.io] Unable to read updates to the logo image file.\n\n"
                              + Utility.GenerateExceptionDebugString(e));
         }
     }
 }
예제 #5
0
        /// <summary>Retrieves a YouTube thumbnail from the cache.</summary>
        public static Texture2D LoadModYouTubeThumbnail(int modId,
                                                        string youTubeId)
        {
            Debug.Assert(!String.IsNullOrEmpty(youTubeId));

            string thumbnailFilePath = CacheClient.GenerateModYouTubeThumbnailFilePath(modId,
                                                                                       youTubeId);

            byte[] imageData;

            if (LocalDataStorage.ReadFile(thumbnailFilePath, out imageData) &&
                imageData != null)
            {
                return(IOUtilities.ParseImageData(imageData));
            }
            else
            {
                return(null);
            }
        }
        // ------[ INITIALIZATION ]------
        public void OnEnable(SerializedProperty serializedEditableModProfile, ModProfile baseProfile, UserProfile user)
        {
            this.editableProfileProperty = serializedEditableModProfile;
            this.profile       = baseProfile;
            this.isUndoEnabled = (baseProfile != null);

            isTagsExpanded = false;
            isKVPsExpanded = false;

            // - Game Profile -
            ModManager.GetGameProfile((g) => { this.gameProfile = g; isRepaintRequired = true; },
                                      null);

            // - Configure Properties -
            logoProperty = editableProfileProperty.FindPropertyRelative("logoLocator");

            // - Load Textures -
            if (logoProperty.FindPropertyRelative("isDirty").boolValue == true)
            {
                logoLocation = logoProperty.FindPropertyRelative("value.url").stringValue;
                logoTexture  = CacheClient.ReadImageFile(logoLocation);
                if (logoTexture != null)
                {
                    lastLogoWriteTime = (new FileInfo(logoLocation)).LastWriteTime;
                }
            }
            else if (profile != null)
            {
                logoLocation = profile.logoLocator.GetSizeURL(LOGO_PREVIEW_SIZE);
                logoTexture  = ApplicationImages.LoadingPlaceholder;

                ModManager.GetModLogo(profile, LOGO_PREVIEW_SIZE,
                                      (t) => { logoTexture = t; isRepaintRequired = true; },
                                      WebRequestError.LogAsWarning);
            }
            else
            {
                logoLocation = string.Empty;
                logoTexture  = null;
            }
        }
예제 #7
0
        /// <summary>Retrieves a mod gallery image from the cache.</summary>
        public static Texture2D LoadModGalleryImage(int modId,
                                                    string imageFileName,
                                                    ModGalleryImageSize size)
        {
            Debug.Assert(!String.IsNullOrEmpty(imageFileName));

            string imageFilePath = CacheClient.GenerateModGalleryImageFilePath(modId,
                                                                               imageFileName,
                                                                               size);

            byte[] imageData;

            if (LocalDataStorage.ReadFile(imageFilePath, out imageData) &&
                imageData != null)
            {
                return(IOUtilities.ParseImageData(imageData));
            }
            else
            {
                return(null);
            }
        }
예제 #8
0
        /// <summary>Stores a mod logo in the cache with the given fileName.</summary>
        public static bool SaveModLogo(int modId, string fileName,
                                       LogoSize size, Texture2D logoTexture)
        {
            Debug.Assert(!String.IsNullOrEmpty(fileName));
            Debug.Assert(logoTexture != null);

            string logoFilePath = CacheClient.GenerateModLogoFilePath(modId, size);
            bool   isSuccessful = IOUtilities.WritePNGFile(logoFilePath, logoTexture);

            // - Update the versioning info -
            var versionInfo = CacheClient.GetModLogoVersionFileNames(modId);

            if (versionInfo == null)
            {
                versionInfo = new Dictionary <LogoSize, string>();
            }
            versionInfo[size] = fileName;
            isSuccessful      = (IOUtilities.WriteJsonObjectFile(GenerateModLogoVersionInfoFilePath(modId), versionInfo) &&
                                 isSuccessful);

            return(isSuccessful);
        }
예제 #9
0
        public static ModBinaryRequest GetActiveModBinary(ModProfile profile)
        {
            string zipFilePath = CacheClient.GenerateModBinaryZipFilePath(profile.id,
                                                                          profile.activeBuild.id);
            ModBinaryRequest request;

            if (File.Exists(zipFilePath))
            {
                request                = new ModBinaryRequest();
                request.isDone         = true;
                request.binaryFilePath = zipFilePath;
            }
            else
            {
                request = DownloadClient.DownloadModBinary(profile.id,
                                                           profile.activeBuild.id,
                                                           CacheClient.GenerateModBinaryZipFilePath(profile.id, profile.activeBuild.id));

                request.succeeded += (r) => CacheClient.SaveModfile(r.modfile);
            }

            return(request);
        }
        // ------[ INITIALIZATION ]------
        protected virtual void OnEnable()
        {
            buildProfile = new EditableModfile();
            buildProfile.version.value = "0.0.0";
            uploadSucceededMessage     = null;
            uploadFailedMessage        = null;

            string authToken = CacheClient.LoadAuthenticatedUserToken();

            if (!String.IsNullOrEmpty(authToken))
            {
                APIClient.userAuthorizationToken = authToken;

                ModManager.GetAuthenticatedUserProfile((userProfile) =>
                {
                    this.user = userProfile;
                    Repaint();
                },
                                                       null);
            }

            LoginWindow.userLoggedIn += OnUserLogin;
        }
예제 #11
0
        private Texture2D GetGalleryImageTexture(string imageFileName,
                                                 string imageSource)
        {
            if (String.IsNullOrEmpty(imageFileName))
            {
                return(null);
            }

            Texture2D texture;

            // - Get -
            if (this.textureCache.TryGetValue(imageFileName, out texture))
            {
                return(texture);
            }
            // - Load -
            else if ((texture = CacheClient.ReadImageFile(imageSource)) != null)
            {
                this.textureCache.Add(imageFileName, texture);
                return(texture);
            }
            // - LoadOrDownload -
            else if (profile != null)
            {
                this.textureCache.Add(imageFileName, ApplicationImages.LoadingPlaceholder);

                ModManager.GetModGalleryImage(profile,
                                              imageFileName,
                                              IMAGE_PREVIEW_SIZE,
                                              (t) => { this.textureCache[imageFileName] = t; isRepaintRequired = true; },
                                              null);
                return(this.textureCache[imageFileName]);
            }

            return(null);
        }
예제 #12
0
        // ---------[ GAME PROFILE ]---------
        public static void GetGameProfile(Action <GameProfile> onSuccess,
                                          Action <WebRequestError> onError)
        {
            GameProfile cachedProfile = CacheClient.LoadGameProfile();

            if (cachedProfile != null)
            {
                onSuccess(cachedProfile);
            }
            else
            {
                Action <GameProfile> onGetProfile = (profile) =>
                {
                    CacheClient.SaveGameProfile(profile);
                    if (onSuccess != null)
                    {
                        onSuccess(profile);
                    }
                };

                APIClient.GetGame(onGetProfile,
                                  onError);
            }
        }
예제 #13
0
        public static void UnzipModBinaryToLocation(ModfileStub modfile,
                                                    string unzipLocation)
        {
            string zipFilePath = CacheClient.GenerateModBinaryZipFilePath(modfile.modId, modfile.id);

            if (File.Exists(zipFilePath))
            {
                try
                {
                    Directory.CreateDirectory(unzipLocation);

                    using (var zip = Ionic.Zip.ZipFile.Read(zipFilePath))
                    {
                        zip.ExtractAll(unzipLocation);
                    }
                }
                catch (Exception e)
                {
                    Debug.LogError("[mod.io] Unable to extract binary to given location."
                                   + "\nLocation: " + unzipLocation + "\n\n"
                                   + Utility.GenerateExceptionDebugString(e));
                }
            }
        }
예제 #14
0
 // ---------[ USERS ]---------
 public static string GenerateUserProfileFilePath(int userId)
 {
     return(CacheClient.GetCacheDirectory()
            + "users/"
            + userId + ".data");
 }
예제 #15
0
 public static void DeleteModTeam(int modId)
 {
     CacheClient.DeleteFile(CacheClient.GenerateModTeamFilePath(modId));
 }
예제 #16
0
 // ---------[ MOD TEAM ]---------
 public static string GenerateModTeamFilePath(int modId)
 {
     return(CacheClient.GenerateModDirectoryPath(modId)
            + "team.data");
 }
예제 #17
0
 public static Dictionary <LogoSize, string> LoadModLogoVersionInfo(int modId)
 {
     return(CacheClient.ReadJsonObjectFile <Dictionary <LogoSize, string> >(CacheClient.GenerateModLogoVersionInfoFilePath(modId)));
 }
예제 #18
0
 public static string GenerateModLogoVersionInfoFilePath(int modId)
 {
     return(CacheClient.GenerateModLogoDirectoryPath(modId)
            + "versionInfo.data");
 }
예제 #19
0
 // ---------[ MOD MEDIA ]---------
 public static string GenerateModLogoDirectoryPath(int modId)
 {
     return(CacheClient.GenerateModDirectoryPath(modId)
            + "logo/");
 }
예제 #20
0
        public static void ApplyModEventsToCache(IEnumerable <ModEvent> modEvents,
                                                 Action <List <ModProfile> > profilesAvailableCallback     = null,
                                                 Action <List <ModProfile> > profilesEditedCallback        = null,
                                                 Action <List <int> > profilesUnavailableCallback          = null,
                                                 Action <List <int> > profilesDeletedCallback              = null,
                                                 Action <List <ModfileStub> > profileBuildsUpdatedCallback = null,
                                                 Action onSuccess = null,
                                                 Action <WebRequestError> onError = null)
        {
            List <int> addedIds          = new List <int>();
            List <int> editedIds         = new List <int>();
            List <int> modfileChangedIds = new List <int>();
            List <int> removedIds        = new List <int>();
            List <int> deletedIds        = new List <int>();

            // Sort by event type
            foreach (ModEvent modEvent in modEvents)
            {
                switch (modEvent.eventType)
                {
                case ModEventType.ModAvailable:
                {
                    addedIds.Add(modEvent.modId);
                }
                break;

                case ModEventType.ModEdited:
                {
                    editedIds.Add(modEvent.modId);
                }
                break;

                case ModEventType.ModfileChanged:
                {
                    modfileChangedIds.Add(modEvent.modId);
                }
                break;

                case ModEventType.ModUnavailable:
                {
                    removedIds.Add(modEvent.modId);
                }
                break;

                case ModEventType.ModDeleted:
                {
                    deletedIds.Add(modEvent.modId);
                }
                break;
                }
            }

            // --- Process Add/Edit/ModfileChanged ---
            List <int> modsToFetch = new List <int>(addedIds.Count + editedIds.Count + modfileChangedIds.Count);

            modsToFetch.AddRange(addedIds);
            modsToFetch.AddRange(editedIds);
            modsToFetch.AddRange(modfileChangedIds);

            if (modsToFetch.Count > 0)
            {
                // - Filter & Pagination -
                RequestFilter modsFilter = new RequestFilter();
                modsFilter.fieldFilters[GetAllModsFilterFields.id]
                    = new InArrayFilter <int>()
                    {
                    filterArray = modsToFetch.ToArray(),
                    };
                // - Get Mods -
                Action <List <ModProfile> > onGetMods = (updatedProfiles) =>
                {
                    // - Create Update Lists -
                    List <ModProfile>  addedProfiles       = new List <ModProfile>(addedIds.Count);
                    List <ModProfile>  editedProfiles      = new List <ModProfile>(editedIds.Count);
                    List <ModfileStub> modfileChangedStubs = new List <ModfileStub>(modfileChangedIds.Count);

                    foreach (ModProfile profile in updatedProfiles)
                    {
                        int idIndex;
                        // NOTE(@jackson): If added, ignore everything else
                        if ((idIndex = addedIds.IndexOf(profile.id)) >= 0)
                        {
                            addedIds.RemoveAt(idIndex);
                            addedProfiles.Add(profile);
                        }
                        else
                        {
                            if ((idIndex = editedIds.IndexOf(profile.id)) >= 0)
                            {
                                editedIds.RemoveAt(idIndex);
                                editedProfiles.Add(profile);
                            }
                            if ((idIndex = modfileChangedIds.IndexOf(profile.id)) >= 0)
                            {
                                modfileChangedIds.RemoveAt(idIndex);
                                modfileChangedStubs.Add(profile.activeBuild);
                            }
                        }
                    }

                    // - Save changed to cache -
                    CacheClient.SaveModProfiles(updatedProfiles);

                    // --- Notifications ---
                    if (profilesAvailableCallback != null &&
                        addedProfiles.Count > 0)
                    {
                        profilesAvailableCallback(addedProfiles);
                    }

                    if (profilesEditedCallback != null &&
                        editedProfiles.Count > 0)
                    {
                        profilesEditedCallback(editedProfiles);
                    }

                    if (profileBuildsUpdatedCallback != null &&
                        modfileChangedStubs.Count > 0)
                    {
                        profileBuildsUpdatedCallback(modfileChangedStubs);
                    }
                };

                ModManager.FetchAllResultsForQuery <ModProfile>((p, s, e) => APIClient.GetAllMods(modsFilter, p, s, e),
                                                                onGetMods,
                                                                null);
            }

            // --- Process Removed ---
            if (removedIds.Count > 0)
            {
                // TODO(@jackson): Compare with subscriptions
                foreach (int modId in removedIds)
                {
                    CacheClient.DeleteMod(modId);
                }

                if (profilesUnavailableCallback != null)
                {
                    profilesUnavailableCallback(removedIds);
                }
            }

            if (deletedIds.Count > 0)
            {
                // TODO(@jackson): Check install state
                foreach (int modId in deletedIds)
                {
                    CacheClient.DeleteMod(modId);
                }

                if (profilesDeletedCallback != null)
                {
                    profilesDeletedCallback(deletedIds);
                }
            }
        }
예제 #21
0
 public static string GenerateModBinaryZipFilePath(int modId, int modfileId)
 {
     return(CacheClient.GenerateModBuildsDirectoryPath(modId)
            + modfileId + ".zip");
 }
예제 #22
0
        public static void DeleteMod(int modId)
        {
            string modDir = CacheClient.GenerateModDirectoryPath(modId);

            CacheClient.DeleteDirectory(modDir);
        }
예제 #23
0
 // ---------[ MOD PROFILES ]---------
 public static string GenerateModProfileFilePath(int modId)
 {
     return(CacheClient.GenerateModDirectoryPath(modId)
            + "profile.data");
 }
예제 #24
0
 public static void SaveGameProfile(GameProfile profile)
 {
     CacheClient.WriteJsonObjectFile(gameProfileFilePath, profile);
 }
예제 #25
0
 public static GameProfile LoadGameProfile()
 {
     return(CacheClient.ReadJsonObjectFile <GameProfile>(gameProfileFilePath));
 }
예제 #26
0
        // ---------[ 2019 ]---------
        /// <summary>Moves the data from the UserAuthenticationData and ModManager caches to UserAccountManagement.</summary>
        private static void Update_2_0_to_2_1_UserData()
        {
            Debug.Log("[mod.io] Attempting 2.0->2.1 UserData update.");

            // check if the file already exists
            byte[] fileData = null;

            UserDataStorage.InitializeForUser(null, () => {});
            UserDataStorage.ReadFile(LocalUser.FILENAME, (success, data) => fileData = data);

            if (fileData != null && fileData.Length > 0)
            {
                Debug.Log("[mod.io] Aborting UserData update. FileExists: \'"
                          + LocalUser.FILENAME + "\' ["
                          + ValueFormatting.ByteCount(fileData.Length, null) + "]");
            }

            // update
            GenericJSONObject dataWrapper;
            LocalUser         userData = new LocalUser();
            string            filePath = null;

            // - copy enabled/subbed -
            filePath = ModManager.PERSISTENTDATA_FILEPATH;

            if (IOUtilities.TryReadJsonObjectFile(filePath, out dataWrapper))
            {
                int[] modIds = null;

                if (DataUpdater.TryGetArrayField(dataWrapper,
                                                 "subscribedModIds",
                                                 out modIds))
                {
                    userData.subscribedModIds = new List <int>(modIds);
                }

                if (DataUpdater.TryGetArrayField(dataWrapper,
                                                 "enabledModIds",
                                                 out modIds))
                {
                    userData.enabledModIds = new List <int>(modIds);
                }
            }

            // - copy queued subs/unsubs -
            filePath = IOUtilities.CombinePath(CacheClient.cacheDirectory,
                                               ModIO.UI.ModBrowser.MANIFEST_FILENAME);

            if (IOUtilities.TryReadJsonObjectFile(filePath, out dataWrapper))
            {
                List <int> modIds = null;

                if (DataUpdater.TryGetArrayField(dataWrapper,
                                                 "queuedSubscribes",
                                                 out modIds))
                {
                    userData.queuedSubscribes = new List <int>(modIds);
                }

                if (DataUpdater.TryGetArrayField(dataWrapper,
                                                 "queuedUnsubscribes",
                                                 out modIds))
                {
                    userData.queuedUnsubscribes = new List <int>(modIds);
                }
            }

            // - copy UAD -
            filePath = UserAuthenticationData.FILE_LOCATION;

            if (IOUtilities.TryReadJsonObjectFile(filePath, out dataWrapper))
            {
                // user profile
                int userId = UserProfile.NULL_ID;
                if (dataWrapper.data.ContainsKey("userId"))
                {
                    userId = (int)dataWrapper.data["userId"];
                }

                userData.profile = null;
                if (userId != UserProfile.NULL_ID)
                {
                    userData.profile = CacheClient.LoadUserProfile(userId);
                }

                // token data
                if (dataWrapper.data.ContainsKey("token"))
                {
                    userData.oAuthToken = (string)dataWrapper.data["token"];
                }
                if (dataWrapper.data.ContainsKey("wasTokenRejected"))
                {
                    userData.wasTokenRejected = (bool)dataWrapper.data["wasTokenRejected"];
                }

                // NOTE(@jackson): External Authentication is no longer saved to disk and is thus ignored.

                IOUtilities.DeleteFile(filePath);
            }

            // - set and save -
            LocalUser.instance = userData;
            LocalUser.isLoaded = true;
            LocalUser.Save();

            Debug.Log("[mod.io] UserData updated completed.");
        }
예제 #27
0
 public static void DeleteUserProfile(int userId)
 {
     CacheClient.DeleteFile(CacheClient.GenerateUserProfileFilePath(userId));
 }
예제 #28
0
 public static void DeleteModfileAndBinaryZip(int modId, int modfileId)
 {
     CacheClient.DeleteFile(CacheClient.GenerateModfileFilePath(modId, modfileId));
     CacheClient.DeleteFile(CacheClient.GenerateModBinaryZipFilePath(modId, modfileId));
 }
예제 #29
0
 public static string GenerateModBuildsDirectoryPath(int modId)
 {
     return(CacheClient.GenerateModDirectoryPath(modId)
            + "builds/");
 }
예제 #30
0
        public static void GetDownloadedBinaryStatus(ModfileStub modfile,
                                                     Action <ModBinaryStatus> callback)
        {
            string          binaryFilePath = CacheClient.GenerateModBinaryZipFilePath(modfile.modId, modfile.id);
            ModBinaryStatus status;

            if (File.Exists(binaryFilePath))
            {
                try
                {
                    if ((new FileInfo(binaryFilePath)).Length != modfile.fileSize)
                    {
                        status = ModBinaryStatus.Error_FileSizeMismatch;
                    }
                    else
                    {
                        using (var md5 = System.Security.Cryptography.MD5.Create())
                        {
                            using (var stream = System.IO.File.OpenRead(binaryFilePath))
                            {
                                var    hash        = md5.ComputeHash(stream);
                                string hashString  = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
                                bool   isValidHash = (hashString == modfile.fileHash.md5);

                                Debug.Log("Hash Validation = [" + isValidHash + "]"
                                          + "\nExpected Hash: " + modfile.fileHash.md5
                                          + "\nDownload Hash: " + hashString);

                                if (isValidHash)
                                {
                                    status = ModBinaryStatus.CompleteAndVerified;
                                }
                                else
                                {
                                    status = ModBinaryStatus.Error_HashCheckFailed;
                                }
                            }
                        }
                    }
                }
                #pragma warning disable 0168

                catch (Exception e)
                {
                    status = ModBinaryStatus.Error_UnableToReadFile;
                }
                #pragma warning restore 0168
            }
            else if (File.Exists(binaryFilePath + ".download"))
            {
                status = ModBinaryStatus.PartiallyDownloaded;
            }
            else
            {
                status = ModBinaryStatus.Missing;
            }

            if (callback != null)
            {
                callback(status);
            }
        }