Example #1
0
        /// <summary>
        /// Asynchronously download a map.
        /// </summary>
        /// <param name="map">The map to download</param>
        /// <param name="url">URL of the online map ZIP</param>
        /// <param name="filePath">Path to local file name</param>
        /// <param name="displayName">Friendly display name</param>
        /// <returns>DownloadResult detailing outcome of the download</returns>
        internal Task <DownloadResult> DownloadMapFile(OverloadMap map, Uri url, string filePath, string displayName)
        {
            DownloadResult result = new DownloadResult();

            var tcs = new TaskCompletionSource <DownloadResult>();

            Task.Run(async() =>
            {
                bool hasProgresChanged = false;
                var timer  = new System.Timers.Timer(new TimeSpan(0, 0, DownloadTimeoutSeconds).TotalMilliseconds);
                var client = new WebClient();

                void downloadHandler(object s, DownloadProgressChangedEventArgs e) => hasProgresChanged = true;

                void timerHandler(object s, ElapsedEventArgs e)
                {
                    timer.Stop();

                    if (hasProgresChanged)
                    {
                        timer.Start();
                        hasProgresChanged = false;
                    }
                    else
                    {
                        result.Message = String.Format($"Timeout downloading {displayName}");

                        CleanUp();
                        tcs.TrySetException(new TimeoutException("Download timed out"));
                    }
                }

                void CleanUp()
                {
                    client.DownloadProgressChanged -= downloadHandler;
                    client.Dispose();
                    timer.Elapsed -= timerHandler;
                    timer.Dispose();
                }

                try
                {
                    client.DownloadProgressChanged += downloadHandler;
                    timer.Elapsed += timerHandler;
                    timer.Start();

                    //LogMessage(String.Format($"Downloading map {displayName}."));

                    await client.DownloadFileTaskAsync(url, filePath);

                    LogMessage(String.Format($"{displayName} download complete."));

                    if (!filePath.Contains(Path.DirectorySeparatorChar + "DLC" + Path.DirectorySeparatorChar))
                    {
                        map.LocalZipFileName = filePath;
                    }
                    else
                    {
                        map.LocalDLCZipFileName = filePath;
                    }

                    map.ZipName = Path.GetFileName(filePath);

                    // Set local files date and time.
                    File.SetCreationTime(filePath, map.DateTime);
                    File.SetLastWriteTime(filePath, map.DateTime);

                    result.Succes = true;
                }
                catch (Exception ex)
                {
                    result.Message = String.Format($"Error downloading {displayName}: {ex.Message}");
                    tcs.TrySetException(ex);
                }
                finally
                {
                    CleanUp();
                }

                return(tcs.TrySetResult(result));
            });

            return(tcs.Task);
        }
Example #2
0
        /// <summary>
        /// Updates both online maps available for download as well as local maps.
        /// </summary>
        /// <param name="mapListUrl">URL to online JSON master map list.</param>
        /// <param name="dlcMaps">Path to local DLC folder (or null).</param>
        /// <param name="applicationMaps">Path to local application folder (or null).</param>
        public void UpdateMapList(string mapListUrl = null, string dlcMaps = null, string applicationMaps = null)
        {
            // Check for override of default URL to JSON map list.
            if (String.IsNullOrEmpty(mapListUrl))
            {
                mapListUrl = DefaultOnlineMapListUrl;
            }

            // Check DLC/application directory names.
            if (!String.IsNullOrEmpty(dlcMaps))
            {
                dlcMapFolder = dlcMaps;

                if (!OverloadServerToolApplication.ValidDirectoryName(dlcMapFolder))
                {
                    LogErrorMessage("DLC directory name is invalid!");
                    return;
                }
            }

            if (!String.IsNullOrEmpty(applicationMaps))
            {
                applicationMapFolder = applicationMaps;

                if (!OverloadServerToolApplication.ValidDirectoryName(applicationMapFolder))
                {
                    LogErrorMessage("Application data directory name is invalid!");
                    return;
                }
            }

            // Need at least one defined folder to store maps.
            if (String.IsNullOrEmpty(applicationMapFolder) && String.IsNullOrEmpty(dlcMapFolder))
            {
                LogErrorMessage("No application data directory or DLC directory found!");
                return;
            }

            // Collect all new online and local maps.
            SortedList <string, OverloadMap> newMapList = new SortedList <String, OverloadMap>();

            // First find all online maps.
            try
            {
                // Get URL base so we can construct full URLs to the online map ZIP files.
                Uri    uri     = new Uri(mapListUrl);
                string baseUrl = String.Concat(uri.Scheme, Uri.SchemeDelimiter, uri.Host);

                // Get map list and build internal map master list.
                string  jsonMapList = new WebClient().DownloadString(mapListUrl);
                dynamic mapList     = JsonConvert.DeserializeObject(jsonMapList);
                foreach (var map in mapList)
                {
                    // Check to make sure it is a ZIP file before adding it to the list.
                    string mapUrl = baseUrl + map.url;
                    Uri    mapUri = new Uri(mapUrl);
                    if (mapUri.Segments.Length > 2)
                    {
                        // Get the ZIP file name from URL.
                        string mapZipName = mapUri.Segments[mapUri.Segments.Length - 1];
                        if (mapZipName.ToLower().EndsWith(".zip"))
                        {
                            // Uppercase first char in map name.
                            mapZipName = mapZipName.Substring(0, 1).ToUpper() + mapZipName.Substring(1);

                            OverloadMap newMap = new OverloadMap(baseUrl + map.url, UnixTimeStampToDateTime(Convert.ToDouble(map.mtime)), Convert.ToInt32(map.size), mapZipName);
                            newMapList.Add(mapZipName.ToLower(), newMap);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                LogErrorMessage(String.Format($"Unable to get online map list: {ex.Message}"));
            }

            // Now add any local maps or update info if existing local map file exists.
            if (OverloadServerToolApplication.ValidDirectoryName(applicationMapFolder))
            {
                try
                {
                    Directory.CreateDirectory(applicationMapFolder);

                    string[] list = Directory.GetFiles(applicationMapFolder, "*.zip*");
                    foreach (string mapFileName in list)
                    {
                        if (mapFileName.EndsWith(HiddenMarker) || mapFileName.ToLower().EndsWith(".zip"))
                        {
                            string mapKey = Path.GetFileName(mapFileName).ToLower();

                            FileInfo    fiLocalMap = new FileInfo(mapFileName);
                            OverloadMap newMap     = new OverloadMap(null, UnixTimeStampToDateTime(0), Convert.ToInt32(fiLocalMap.Length), mapFileName);

                            bool found = false;
                            foreach (KeyValuePair <string, OverloadMap> map in newMapList)
                            {
                                if (newMap.SameZipFileName(map.Value))
                                {
                                    // We found a local map that matches the ZIP filename as found online.
                                    found = true;

                                    // Uppercase first char in map name and remove hidden marker if present.
                                    string mapZipName = fiLocalMap.Name;
                                    mapZipName        = mapZipName.Substring(0, 1).ToUpper() + mapZipName.Substring(1);
                                    mapZipName        = mapZipName.Replace(HiddenMarker, "");
                                    map.Value.ZipName = mapZipName;

                                    // Save full path to ZIP file in the application data folder.
                                    map.Value.LocalZipFileName = fiLocalMap.FullName;
                                }
                            }

                            if (!found)
                            {
                                newMapList.Add(mapFileName.ToLower(), newMap);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogErrorMessage(String.Format($"Unable to get local maps: {ex.Message}"));
                }
            }

            if (OverloadServerToolApplication.ValidDirectoryName(dlcMapFolder))
            {
                try
                {
                    Directory.CreateDirectory(dlcMapFolder);

                    string[] list = Directory.GetFiles(dlcMapFolder, "*.zip*");
                    foreach (string mapFileName in list)
                    {
                        if (mapFileName.EndsWith(HiddenMarker) || mapFileName.ToLower().EndsWith(".zip"))
                        {
                            string      mapKey     = Path.GetFileName(mapFileName).ToLower();
                            FileInfo    fiLocalMap = new FileInfo(mapFileName);
                            OverloadMap newMap     = new OverloadMap(null, UnixTimeStampToDateTime(0), Convert.ToInt32(fiLocalMap.Length), mapFileName);

                            bool found = false;
                            foreach (KeyValuePair <string, OverloadMap> map in newMapList)
                            {
                                if (newMap.SameZipFileName(map.Value))
                                {
                                    // We found a local map that matches the ZIP filename as found online.
                                    found = true;
                                    // Uppercase first char in map name and remove hidden marker if present.
                                    string mapZipName = fiLocalMap.Name;
                                    mapZipName        = mapZipName.Substring(0, 1).ToUpper() + mapZipName.Substring(1);
                                    mapZipName        = mapZipName.Replace(HiddenMarker, "");
                                    map.Value.ZipName = mapZipName;

                                    // Save full path to ZIP file in the DLC folder.
                                    map.Value.LocalDLCZipFileName = fiLocalMap.FullName;
                                }
                            }

                            if (!found)
                            {
                                newMapList.Add(mapFileName.ToLower(), newMap);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    LogErrorMessage(String.Format($"Unable to get local maps: {ex.Message}"));
                }
            }

            // Update maps.
            Maps = newMapList;
        }
Example #3
0
        /// <summary>
        /// Update a single Overload map.
        /// </summary>
        /// <param name="map">The map to update.</param>
        /// <returns></returns>
        public async Task <bool> UpdateMap(OverloadMap map, bool forceUpdate)
        {
            Checked++;

            if (String.IsNullOrEmpty(map.Url))
            {
                return(false);
            }

            string mapZipName        = map.ZipName;
            string mapDirectoryPath  = (String.IsNullOrEmpty(dlcMapFolder) || !SaveNewMapsToDLCFolder) ? applicationMapFolder : dlcMapFolder;
            string mapZipFilePath    = WebUtility.UrlDecode(Path.Combine(mapDirectoryPath, mapZipName));
            string mapZipDisplayName = WebUtility.UrlDecode(mapZipName).Trim();

            // Check if we should use existing download path.
            if (map.InDLCFolder)
            {
                mapDirectoryPath = Path.GetDirectoryName(map.LocalDLCZipFileName);
                mapZipFilePath   = map.LocalDLCZipFileName;
            }
            else if (map.InApplicationDataFolder)
            {
                mapDirectoryPath = Path.GetDirectoryName(map.LocalZipFileName);
                mapZipFilePath   = map.LocalZipFileName;
            }

            // Create (DLC or application data) directory if it doesn't exist.
            if (!Directory.Exists(mapDirectoryPath))
            {
                Directory.CreateDirectory(mapDirectoryPath);
            }

            // Don't update hidden maps.
            if (File.Exists(mapZipFilePath + HiddenMarker))
            {
                return(false);
            }

            // Check for new map file.
            if (!forceUpdate && OverloadServerToolApplication.ValidFileName(mapZipFilePath))
            {
                if (File.Exists(mapZipFilePath))
                {
                    // Map already downloaded. Compare date and size against online version.
                    FileInfo fi = new FileInfo(mapZipFilePath);
                    if ((fi.Length == map.Size) && (fi.LastWriteTime == map.DateTime))
                    {
                        return(false);
                    }
                }
                else
                {
                    // Only update existing maps?
                    if (OnlyUpdateExistingMaps)
                    {
                        return(false);
                    }
                }
            }

            try
            {
                bool existingFile = File.Exists(mapZipFilePath);

                // Download map.
                DownloadResult result = await DownloadMapFile(map, new Uri(map.Url), mapZipFilePath, mapZipDisplayName);

                if (result.Exception != null)
                {
                    throw result.Exception;
                }
                if (result.Succes == false)
                {
                    if (String.IsNullOrEmpty(result.Message))
                    {
                        result.Message = String.Format($"Unable to download {mapZipDisplayName}");
                    }
                    try { File.Delete(mapZipFilePath); } catch { }
                    throw new Exception(String.Format($"Unable to download {result.Message }"));
                }

                // LogMessage(String.Format($"Downloading map {mapZipDisplayName}."));

                if (existingFile)
                {
                    Updated++;
                }
                else
                {
                    Created++;
                }

                return(true);
            }
            catch (Exception ex)
            {
                Errors++;

                LogErrorMessage(String.Format($"Error downloading {mapZipDisplayName}: {ex.Message}"));
                return(false);
            }
        }
Example #4
0
 /// <summary>
 /// Returns TRUE if this map has the same ZIP map filename as 'compareToMap'
 /// Doesn't matter if either map is hidden or not.
 /// </summary>
 /// <param name="compareZipName"></param>
 /// <returns></returns>
 public bool SameZipFileName(OverloadMap compareToMap)
 {
     return(compareToMap.ZipName.Replace(MapHiddenMarker, "").ToLower() == this.ZipName.ToLower().Replace(MapHiddenMarker, ""));
 }