using System; using System.Collections.Generic; using System.IO; using System.Net; using AllocsFixes; using UnityEngine; using Object = UnityEngine.Object; namespace Webserver.UrlHandlers { public class ItemIconHandler : AbsHandler { private readonly Dictionary icons = new Dictionary (); private readonly bool logMissingFiles; private bool loaded; static ItemIconHandler () { Instance = null; } public ItemIconHandler (bool _logMissingFiles, string _moduleName = null) : base (_moduleName) { logMissingFiles = _logMissingFiles; Instance = this; } public static ItemIconHandler Instance { get; private set; } public override void HandleRequest (RequestContext _context) { if (!loaded) { _context.Response.StatusCode = (int) HttpStatusCode.InternalServerError; Log.Out ("[Web] IconHandler: Icons not loaded"); return; } string requestFileName = _context.RequestPath.Remove (0, urlBasePath.Length); requestFileName = requestFileName.Remove (requestFileName.LastIndexOf ('.')); if (icons.ContainsKey (requestFileName) && _context.RequestPath.EndsWith (".png", StringComparison.OrdinalIgnoreCase)) { _context.Response.ContentType = MimeType.GetMimeType (".png"); byte[] itemIconData = icons [requestFileName]; _context.Response.ContentLength64 = itemIconData.Length; _context.Response.OutputStream.Write (itemIconData, 0, itemIconData.Length); } else { _context.Response.StatusCode = (int) HttpStatusCode.NotFound; if (logMissingFiles) { Log.Out ("[Web] IconHandler: FileNotFound: \"" + _context.RequestPath + "\" "); } } } public bool LoadIcons () { lock (icons) { if (loaded) { return true; } MicroStopwatch microStopwatch = new MicroStopwatch (); // Get list of used tints for all items Dictionary> tintedIcons = new Dictionary> (); foreach (ItemClass ic in ItemClass.list) { if (ic == null) { continue; } Color tintColor = ic.GetIconTint (); if (tintColor == Color.white) { continue; } string name = ic.GetIconName (); if (!tintedIcons.ContainsKey (name)) { tintedIcons.Add (name, new List ()); } List list = tintedIcons [name]; list.Add (tintColor); } try { loadIconsFromFolder (GameIO.GetGameDir ("Data/ItemIcons"), tintedIcons); } catch (Exception e) { Log.Error ("[Web] Failed loading icons from base game"); Log.Exception (e); } // Load icons from mods foreach (Mod mod in ModManager.GetLoadedMods ()) { try { string modIconsPath = mod.Path + "/ItemIcons"; loadIconsFromFolder (modIconsPath, tintedIcons); } catch (Exception e) { Log.Error ("[Web] Failed loading icons from mod " + mod.ModInfo.Name.Value); Log.Exception (e); } } loaded = true; Log.Out ("[Web] IconHandler: Icons loaded - {0} ms", microStopwatch.ElapsedMilliseconds); return true; } } private void loadIconsFromFolder (string _path, Dictionary> _tintedIcons) { if (!Directory.Exists (_path)) { return; } foreach (string file in Directory.GetFiles (_path)) { try { if (!file.EndsWith (".png", StringComparison.OrdinalIgnoreCase)) { continue; } string name = Path.GetFileNameWithoutExtension (file); Texture2D tex = new Texture2D (1, 1, TextureFormat.ARGB32, false); if (!tex.LoadImage (File.ReadAllBytes (file))) { continue; } AddIcon (name, tex, _tintedIcons); Object.Destroy (tex); } catch (Exception e) { Log.Exception (e); } } } private void AddIcon (string _name, Texture2D _tex, Dictionary> _tintedIcons) { icons [_name + "__FFFFFF"] = _tex.EncodeToPNG (); if (!_tintedIcons.ContainsKey (_name)) { return; } foreach (Color c in _tintedIcons [_name]) { string tintedName = _name + "__" + AllocsUtils.ColorToHex (c); if (icons.ContainsKey (tintedName)) { continue; } Texture2D tintedTex = new Texture2D (_tex.width, _tex.height, TextureFormat.ARGB32, false); for (int x = 0; x < _tex.width; x++) { for (int y = 0; y < _tex.height; y++) { tintedTex.SetPixel (x, y, _tex.GetPixel (x, y) * c); } } icons [tintedName] = tintedTex.EncodeToPNG (); Object.Destroy (tintedTex); } } } }