using System; using System.Collections.Generic; using System.IO; using System.Net; using UnityEngine; using Object = UnityEngine.Object; namespace AllocsFixes.NetConnections.Servers.Web.Handlers { public class ItemIconHandler : PathHandler { private readonly Dictionary icons = new Dictionary (); private readonly bool logMissingFiles; private readonly string staticPart; private bool loaded; static ItemIconHandler () { Instance = null; } public ItemIconHandler (string staticPart, bool logMissingFiles, string moduleName = null) : base (moduleName) { this.staticPart = staticPart; this.logMissingFiles = logMissingFiles; Instance = this; } public static ItemIconHandler Instance { get; private set; } public override void HandleRequest (HttpListenerRequest req, HttpListenerResponse resp, WebConnection user, int permissionLevel) { if (!loaded) { resp.StatusCode = (int) HttpStatusCode.InternalServerError; Log.Out ("Web:IconHandler: Icons not loaded"); return; } string requestFileName = req.Url.AbsolutePath.Remove (0, staticPart.Length); requestFileName = requestFileName.Remove (requestFileName.LastIndexOf ('.')); if (icons.ContainsKey (requestFileName) && req.Url.AbsolutePath.EndsWith (".png", StringComparison.OrdinalIgnoreCase)) { resp.ContentType = MimeType.GetMimeType (".png"); byte[] itemIconData = icons [requestFileName]; resp.ContentLength64 = itemIconData.Length; resp.OutputStream.Write (itemIconData, 0, itemIconData.Length); } else { resp.StatusCode = (int) HttpStatusCode.NotFound; if (logMissingFiles) { Log.Out ("Web:IconHandler:FileNotFound: \"" + req.Url.AbsolutePath + "\" "); } } } public bool LoadIcons () { lock (icons) { if (loaded) { return true; } MicroStopwatch microStopwatch = new MicroStopwatch (); GameObject atlasObj = GameObject.Find ("/NGUI Root (2D)/ItemIconAtlas"); if (atlasObj == null) { Log.Error ("Web:IconHandler: Atlas object not found"); loaded = true; return false; } DynamicUIAtlas atlas = atlasObj.GetComponent (); if (atlas == null) { Log.Error ("Web:IconHandler: Atlas component not found"); loaded = true; return false; } string textureResourceName = atlas.PrebakedAtlas; List sprites; int elementWidth, elementHeight; Texture2D atlasTex; if (!DynamicUIAtlasTools.ReadPrebakedAtlasDescriptor (textureResourceName, out sprites, out elementWidth, out elementHeight)) { SdtdConsole.Instance.Output ("Web:IconHandler: Could not read dynamic atlas descriptor"); return false; } if (!DynamicUIAtlasTools.ReadPrebakedAtlasTexture (textureResourceName, out atlasTex)) { SdtdConsole.Instance.Output ("Web:IconHandler: Could not read dynamic atlas texture"); return false; } // Get list of used tints for all items Dictionary> tintedIcons = new Dictionary> (); foreach (ItemClass ic in ItemClass.list) { if (ic != null) { Color tintColor = ic.GetIconTint (); if (tintColor != Color.white) { string name = ic.GetIconName (); if (!tintedIcons.ContainsKey (name)) { tintedIcons.Add (name, new List ()); } List list = tintedIcons [name]; list.Add (tintColor); } } } // Load icons from vanilla foreach (UISpriteData data in sprites) { string name = data.name; Texture2D tex = new Texture2D (data.width, data.height, TextureFormat.ARGB32, false); tex.SetPixels (atlasTex.GetPixels (data.x, atlasTex.height - data.height - data.y, data.width, data.height)); AddIcon (name, tex, tintedIcons); Object.Destroy (tex); } Resources.UnloadAsset (atlasTex); // Load icons from mods foreach (Mod mod in ModManager.GetLoadedMods ()) { try { string modIconsPath = mod.Path + "/ItemIcons"; if (Directory.Exists (modIconsPath)) { foreach (string file in Directory.GetFiles (modIconsPath)) { try { if (file.EndsWith (".png", StringComparison.OrdinalIgnoreCase)) { string name = Path.GetFileNameWithoutExtension (file); Texture2D tex = new Texture2D (1, 1, TextureFormat.ARGB32, false); if (tex.LoadImage (File.ReadAllBytes (file))) { if (tex.width == elementWidth && tex.height == elementHeight) { AddIcon (name, tex, tintedIcons); } Object.Destroy (tex); } } } catch (Exception e) { Log.Exception (e); } } } } catch (Exception e) { Log.Exception (e); } } loaded = true; Log.Out ("Web:IconHandler: Icons loaded - {0} ms", microStopwatch.ElapsedMilliseconds); return true; } } private void AddIcon (string _name, Texture2D _tex, Dictionary> _tintedIcons) { icons [_name + "__FFFFFF"] = _tex.EncodeToPNG (); if (_tintedIcons.ContainsKey (_name)) { foreach (Color c in _tintedIcons [_name]) { string tintedName = _name + "__" + AllocsUtils.ColorToHex (c); if (!icons.ContainsKey (tintedName)) { 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); } } } } } }